Added all required dependencies

This commit is contained in:
Thomas Boerger 2016-11-03 23:16:01 +01:00
parent 78f86abba4
commit 1ebb35b988
No known key found for this signature in database
GPG key ID: 5A388F55283960B6
660 changed files with 502447 additions and 0 deletions

191
vendor/github.com/go-macaron/binding/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

20
vendor/github.com/go-macaron/binding/README.md generated vendored Normal file
View file

@ -0,0 +1,20 @@
# binding [![Build Status](https://travis-ci.org/go-macaron/binding.svg?branch=master)](https://travis-ci.org/go-macaron/binding) [![](http://gocover.io/_badge/github.com/go-macaron/binding)](http://gocover.io/github.com/go-macaron/binding)
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.

669
vendor/github.com/go-macaron/binding/binding.go generated vendored Normal file
View file

@ -0,0 +1,669 @@
// 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"
"reflect"
"regexp"
"strconv"
"strings"
"unicode/utf8"
"github.com/Unknwon/com"
"gopkg.in/macaron.v1"
)
const _VERSION = "0.3.2"
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())
}
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
}
}
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...)
}
}
// 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 errors 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()
errors = validateStruct(errors, e)
if validator, ok := e.(Validator); ok {
errors = validator.Validate(ctx, errors)
}
}
} else {
errors = validateStruct(errors, obj)
if validator, ok := obj.(Validator); ok {
errors = validator.Validate(ctx, errors)
}
}
ctx.Map(errors)
}
}
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])?")
URLPattern = regexp.MustCompile(`(http|https):\/\/(?:\\S+(?::\\S*)?@)?[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?`)
)
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)
}
// RuleMapper represents a validation rule mapper,
// it allwos users to add custom validation rules.
RuleMapper []*Rule
)
var ruleMapper RuleMapper
// AddRule adds new validation rule.
func AddRule(r *Rule) {
ruleMapper = append(ruleMapper, 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":
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 !URLPattern.MatchString(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() {
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
}
}
}
}
}
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) {
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()))
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 {
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++ {
setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
}
formStruct.Field(i).Set(slice)
} else {
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]))
}
}
}
// 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) {
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)
return
}
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)
}
}
// 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/github.com/go-macaron/binding/errors.go generated vendored Normal file
View 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
}

191
vendor/github.com/go-macaron/cache/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

20
vendor/github.com/go-macaron/cache/README.md generated vendored Normal file
View file

@ -0,0 +1,20 @@
# cache [![Build Status](https://travis-ci.org/go-macaron/cache.svg?branch=master)](https://travis-ci.org/go-macaron/cache) [![](http://gocover.io/_badge/github.com/go-macaron/cache)](http://gocover.io/github.com/go-macaron/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 github.com/go-macaron/cache
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-macaron/cache)
- [Documentation](http://go-macaron.com/docs/middlewares/cache)
## Credits
This package is a modified version of [beego/cache](https://github.com/astaxie/beego/tree/master/cache).
## License
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

122
vendor/github.com/go-macaron/cache/cache.go generated vendored Normal file
View 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"
"gopkg.in/macaron.v1"
)
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/github.com/go-macaron/cache/file.go generated vendored Normal file
View 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"
"github.com/Unknwon/com"
"gopkg.in/macaron.v1"
)
// 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())
}

View 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/Unknwon/com"
"github.com/bradfitz/gomemcache/memcache"
"github.com/go-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{})
}

View file

@ -0,0 +1 @@
ignore

179
vendor/github.com/go-macaron/cache/memory.go generated vendored Normal file
View 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/github.com/go-macaron/cache/redis/redis.go generated vendored Normal file
View 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/Unknwon/com"
"gopkg.in/ini.v1"
"gopkg.in/redis.v2"
"github.com/go-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)).Err(); err != nil {
return err
}
} else {
dur, err := time.ParseDuration(com.ToStr(expire) + "s")
if err != nil {
return err
}
if err = c.c.SetEx(key, dur, com.ToStr(val)).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() {
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).MustInt64()
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{})
}

View file

@ -0,0 +1 @@
ignore

84
vendor/github.com/go-macaron/cache/utils.go generated vendored Normal file
View 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
}

191
vendor/github.com/go-macaron/captcha/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

16
vendor/github.com/go-macaron/captcha/README.md generated vendored Normal file
View file

@ -0,0 +1,16 @@
# captcha [![Build Status](https://travis-ci.org/go-macaron/captcha.svg?branch=master)](https://travis-ci.org/go-macaron/captcha)
Middleware captcha provides captcha service for [Macaron](https://github.com/go-macaron/macaron).
### Installation
go get github.com/go-macaron/captcha
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-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.

241
vendor/github.com/go-macaron/captcha/captcha.go generated vendored Normal file
View file

@ -0,0 +1,241 @@
// 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"
"path"
"strings"
"github.com/Unknwon/com"
"github.com/go-macaron/cache"
"gopkg.in/macaron.v1"
)
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
}
// 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...))
}
// tempalte func for output html
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="%s" value="%s">
<a class="captcha" href="javascript:">
<img onclick="this.src=('%s%s%s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%s%s%s.png">
</a>`, c.FieldIdName, value, c.SubURL, c.URLPrefix, value, c.SubURL, c.URLPrefix, value))
}
// 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
}
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,
}
}
// 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).WriteTo(ctx.Resp); err != nil {
panic(fmt.Errorf("write captcha: %v", err))
}
return
}
ctx.Data["Captcha"] = cpt
ctx.Map(cpt)
}
}

498
vendor/github.com/go-macaron/captcha/image.go generated vendored Normal file
View file

@ -0,0 +1,498 @@
// 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() color.Palette {
p := make([]color.Color, circleCount+1)
// Transparent color.
p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
// Primary color.
prim := color.RGBA{
uint8(randIntn(129)),
uint8(randIntn(129)),
uint8(randIntn(129)),
0xFF,
}
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.
func NewImage(digits []byte, width, height int) *Image {
m := new(Image)
m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette())
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/github.com/go-macaron/captcha/siprng.go generated vendored Normal file
View 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) }

191
vendor/github.com/go-macaron/csrf/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

18
vendor/github.com/go-macaron/csrf/README.md generated vendored Normal file
View file

@ -0,0 +1,18 @@
# csrf [![Build Status](https://travis-ci.org/go-macaron/csrf.svg?branch=master)](https://travis-ci.org/go-macaron/csrf) [![](http://gocover.io/_badge/github.com/go-macaron/csrf)](http://gocover.io/github.com/go-macaron/csrf)
Middleware csrf generates and validates CSRF tokens for [Macaron](https://github.com/go-macaron/macaron).
[API Reference](https://gowalker.org/github.com/go-macaron/csrf)
### Installation
go get github.com/go-macaron/csrf
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-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.

251
vendor/github.com/go-macaron/csrf/csrf.go generated vendored Normal file
View file

@ -0,0 +1,251 @@
// 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"
"github.com/Unknwon/com"
"github.com/go-macaron/session"
"gopkg.in/macaron.v1"
)
const _VERSION = "0.1.0"
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 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 path
CookiePath string
// 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
}
// 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 path.
CookiePath string
// 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,
CookiePath: opt.CookiePath,
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, "", false, true, 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)
}

97
vendor/github.com/go-macaron/csrf/xsrf.go generated vendored Normal file
View 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.URLEncoding.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.URLEncoding.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
}

191
vendor/github.com/go-macaron/gzip/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

20
vendor/github.com/go-macaron/gzip/README.md generated vendored Normal file
View file

@ -0,0 +1,20 @@
# gzip [![Build Status](https://travis-ci.org/go-macaron/gzip.svg?branch=master)](https://travis-ci.org/go-macaron/gzip) [![](http://gocover.io/_badge/github.com/go-macaron/gzip)](http://gocover.io/github.com/go-macaron/gzip)
Middleware gzip provides compress to responses for [Macaron](https://github.com/go-macaron/macaron).
### Installation
go get github.com/go-macaron/gzip
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-macaron/gzip)
- [Documentation](http://go-macaron.com/docs/middlewares/gzip)
## Credits
This package is a modified version of [martini-contrib/gzip](https://github.com/martini-contrib/gzip).
## License
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

121
vendor/github.com/go-macaron/gzip/gzip.go generated vendored Normal file
View file

@ -0,0 +1,121 @@
// Copyright 2013 Martini Authors
// 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 gzip
import (
"bufio"
"fmt"
"net"
"net/http"
"strings"
"github.com/klauspost/compress/gzip"
"gopkg.in/macaron.v1"
)
const (
_HEADER_ACCEPT_ENCODING = "Accept-Encoding"
_HEADER_CONTENT_ENCODING = "Content-Encoding"
_HEADER_CONTENT_LENGTH = "Content-Length"
_HEADER_CONTENT_TYPE = "Content-Type"
_HEADER_VARY = "Vary"
)
// Options represents a struct for specifying configuration options for the GZip middleware.
type Options struct {
// Compression level. Can be DefaultCompression(-1), ConstantCompression(-2)
// or any integer value between BestSpeed(1) and BestCompression(9) inclusive.
CompressionLevel int
}
func isCompressionLevelValid(level int) bool {
return level == gzip.DefaultCompression ||
level == gzip.ConstantCompression ||
(level >= gzip.BestSpeed && level <= gzip.BestCompression)
}
func prepareOptions(options []Options) Options {
var opt Options
if len(options) > 0 {
opt = options[0]
}
if !isCompressionLevelValid(opt.CompressionLevel) {
// For web content, level 4 seems to be a sweet spot.
opt.CompressionLevel = 4
}
return opt
}
// Gziper returns a Handler that adds gzip compression to all requests.
// Make sure to include the Gzip middleware above other middleware
// that alter the response body (like the render middleware).
func Gziper(options ...Options) macaron.Handler {
opt := prepareOptions(options)
return func(ctx *macaron.Context) {
if !strings.Contains(ctx.Req.Header.Get(_HEADER_ACCEPT_ENCODING), "gzip") {
return
}
headers := ctx.Resp.Header()
headers.Set(_HEADER_CONTENT_ENCODING, "gzip")
headers.Set(_HEADER_VARY, _HEADER_ACCEPT_ENCODING)
// We've made sure compression level is valid in prepareGzipOptions,
// no need to check same error again.
gz, err := gzip.NewWriterLevel(ctx.Resp, opt.CompressionLevel)
if err != nil {
panic(err.Error())
}
defer gz.Close()
gzw := gzipResponseWriter{gz, ctx.Resp}
ctx.Resp = gzw
ctx.MapTo(gzw, (*http.ResponseWriter)(nil))
// Check if render middleware has been registered,
// if yes, we need to modify ResponseWriter for it as well.
if _, ok := ctx.Render.(*macaron.DummyRender); !ok {
ctx.Render.SetResponseWriter(gzw)
}
ctx.Next()
// delete content length after we know we have been written to
gzw.Header().Del("Content-Length")
}
}
type gzipResponseWriter struct {
w *gzip.Writer
macaron.ResponseWriter
}
func (grw gzipResponseWriter) Write(p []byte) (int, error) {
if len(grw.Header().Get(_HEADER_CONTENT_TYPE)) == 0 {
grw.Header().Set(_HEADER_CONTENT_TYPE, http.DetectContentType(p))
}
return grw.w.Write(p)
}
func (grw gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := grw.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
}
return hijacker.Hijack()
}

191
vendor/github.com/go-macaron/i18n/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

16
vendor/github.com/go-macaron/i18n/README.md generated vendored Normal file
View file

@ -0,0 +1,16 @@
# i18n [![Build Status](https://travis-ci.org/go-macaron/i18n.svg?branch=master)](https://travis-ci.org/go-macaron/i18n) [![](http://gocover.io/_badge/github.com/go-macaron/i18n)](http://gocover.io/github.com/go-macaron/i18n)
Middleware i18n provides app Internationalization and Localization for [Macaron](https://github.com/go-macaron/macaron).
### Installation
go get github.com/go-macaron/i18n
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-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.

225
vendor/github.com/go-macaron/i18n/i18n.go generated vendored Normal file
View file

@ -0,0 +1,225 @@
// 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"
"github.com/Unknwon/com"
"github.com/Unknwon/i18n"
"golang.org/x/text/language"
"gopkg.in/macaron.v1"
)
const _VERSION = "0.3.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
}
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, "/"))
}
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, "?")])
}
}
}

191
vendor/github.com/go-macaron/inject/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

11
vendor/github.com/go-macaron/inject/README.md generated vendored Normal file
View file

@ -0,0 +1,11 @@
# inject [![Build Status](https://travis-ci.org/go-macaron/inject.svg?branch=master)](https://travis-ci.org/go-macaron/inject) [![](http://gocover.io/_badge/github.com/go-macaron/inject)](http://gocover.io/github.com/go-macaron/inject)
Package inject provides utilities for mapping and injecting dependencies in various ways.
**This a modified version of [codegangsta/inject](https://github.com/codegangsta/inject) for special purpose of Macaron**
**Please use the original version if you need dependency injection feature**
## License
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

262
vendor/github.com/go-macaron/inject/inject.go generated vendored Normal file
View file

@ -0,0 +1,262 @@
// Copyright 2013 Jeremy Saenz
// Copyright 2015 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
// Package inject provides utilities for mapping and injecting dependencies in various ways.
package inject
import (
"fmt"
"reflect"
)
// Injector represents an interface for mapping and injecting dependencies into structs
// and function arguments.
type Injector interface {
Applicator
Invoker
TypeMapper
// SetParent sets the parent of the injector. If the injector cannot find a
// dependency in its Type map it will check its parent before returning an
// error.
SetParent(Injector)
}
// Applicator represents an interface for mapping dependencies to a struct.
type Applicator interface {
// Maps dependencies in the Type map to each field in the struct
// that is tagged with 'inject'. Returns an error if the injection
// fails.
Apply(interface{}) error
}
// Invoker represents an interface for calling functions via reflection.
type Invoker interface {
// Invoke attempts to call the interface{} provided as a function,
// providing dependencies for function arguments based on Type. Returns
// a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
Invoke(interface{}) ([]reflect.Value, error)
}
// FastInvoker represents an interface in order to avoid the calling function via reflection.
//
// example:
// type handlerFuncHandler func(http.ResponseWriter, *http.Request) error
// func (f handlerFuncHandler)Invoke([]interface{}) ([]reflect.Value, error){
// ret := f(p[0].(http.ResponseWriter), p[1].(*http.Request))
// return []reflect.Value{reflect.ValueOf(ret)}, nil
// }
//
// type funcHandler func(int, string)
// func (f funcHandler)Invoke([]interface{}) ([]reflect.Value, error){
// f(p[0].(int), p[1].(string))
// return nil, nil
// }
type FastInvoker interface {
// Invoke attempts to call the ordinary functions. If f is a function
// with the appropriate signature, f.Invoke([]interface{}) is a Call that calls f.
// Returns a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
Invoke([]interface{}) ([]reflect.Value, error)
}
// IsFastInvoker check interface is FastInvoker
func IsFastInvoker(h interface{}) bool {
_, ok := h.(FastInvoker)
return ok
}
// TypeMapper represents an interface for mapping interface{} values based on type.
type TypeMapper interface {
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
Map(interface{}) TypeMapper
// Maps the interface{} value based on the pointer of an Interface provided.
// This is really only useful for mapping a value as an interface, as interfaces
// cannot at this time be referenced directly without a pointer.
MapTo(interface{}, interface{}) TypeMapper
// Provides a possibility to directly insert a mapping based on type and value.
// This makes it possible to directly map type arguments not possible to instantiate
// with reflect like unidirectional channels.
Set(reflect.Type, reflect.Value) TypeMapper
// Returns the Value that is mapped to the current type. Returns a zeroed Value if
// the Type has not been mapped.
GetVal(reflect.Type) reflect.Value
}
type injector struct {
values map[reflect.Type]reflect.Value
parent Injector
}
// InterfaceOf dereferences a pointer to an Interface type.
// It panics if value is not an pointer to an interface.
func InterfaceOf(value interface{}) reflect.Type {
t := reflect.TypeOf(value)
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Interface {
panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
}
return t
}
// New returns a new Injector.
func New() Injector {
return &injector{
values: make(map[reflect.Type]reflect.Value),
}
}
// Invoke attempts to call the interface{} provided as a function,
// providing dependencies for function arguments based on Type.
// Returns a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
// It panics if f is not a function
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
t := reflect.TypeOf(f)
switch v := f.(type) {
case FastInvoker:
return inj.fastInvoke(v, t, t.NumIn())
default:
return inj.callInvoke(f, t, t.NumIn())
}
}
func (inj *injector) fastInvoke(f FastInvoker, t reflect.Type, numIn int) ([]reflect.Value, error) {
var in []interface{}
if numIn > 0 {
in = make([]interface{}, numIn) // Panic if t is not kind of Func
var argType reflect.Type
var val reflect.Value
for i := 0; i < numIn; i++ {
argType = t.In(i)
val = inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}
in[i] = val.Interface()
}
}
return f.Invoke(in)
}
// callInvoke reflect.Value.Call
func (inj *injector) callInvoke(f interface{}, t reflect.Type, numIn int) ([]reflect.Value, error) {
var in []reflect.Value
if numIn > 0 {
in = make([]reflect.Value, numIn)
var argType reflect.Type
var val reflect.Value
for i := 0; i < numIn; i++ {
argType = t.In(i)
val = inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}
in[i] = val
}
}
return reflect.ValueOf(f).Call(in), nil
}
// Maps dependencies in the Type map to each field in the struct
// that is tagged with 'inject'.
// Returns an error if the injection fails.
func (inj *injector) Apply(val interface{}) error {
v := reflect.ValueOf(val)
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil // Should not panic here ?
}
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
structField := t.Field(i)
if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
ft := f.Type()
v := inj.GetVal(ft)
if !v.IsValid() {
return fmt.Errorf("Value not found for type %v", ft)
}
f.Set(v)
}
}
return nil
}
// Maps the concrete value of val to its dynamic type using reflect.TypeOf,
// It returns the TypeMapper registered in.
func (i *injector) Map(val interface{}) TypeMapper {
i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
return i
}
func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
return i
}
// Maps the given reflect.Type to the given reflect.Value and returns
// the Typemapper the mapping has been registered in.
func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
i.values[typ] = val
return i
}
func (i *injector) GetVal(t reflect.Type) reflect.Value {
val := i.values[t]
if val.IsValid() {
return val
}
// no concrete types found, try to find implementors
// if t is an interface
if t.Kind() == reflect.Interface {
for k, v := range i.values {
if k.Implements(t) {
val = v
break
}
}
}
// Still no type found, try to look it up on the parent
if !val.IsValid() && i.parent != nil {
val = i.parent.GetVal(t)
}
return val
}
func (i *injector) SetParent(parent Injector) {
i.parent = parent
}

191
vendor/github.com/go-macaron/session/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

20
vendor/github.com/go-macaron/session/README.md generated vendored Normal file
View file

@ -0,0 +1,20 @@
# session [![Build Status](https://travis-ci.org/go-macaron/session.svg?branch=master)](https://travis-ci.org/go-macaron/session) [![](http://gocover.io/_badge/github.com/go-macaron/session)](http://gocover.io/github.com/go-macaron/session)
Middleware session provides session management for [Macaron](https://github.com/go-macaron/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
### Installation
go get github.com/go-macaron/session
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-macaron/session)
- [Documentation](http://go-macaron.com/docs/middlewares/session)
## Credits
This package is a modified version of [beego/session](https://github.com/astaxie/beego/tree/master/session).
## License
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

261
vendor/github.com/go-macaron/session/file.go generated vendored Normal file
View file

@ -0,0 +1,261 @@
// 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()
data, err := EncodeGob(s.data)
if err != nil {
return err
}
return ioutil.WriteFile(s.p.filepath(s.sid), data, os.ModePerm)
}
// 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), os.ModePerm); 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_RDWR, os.ModePerm)
} 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))
}
// Destory deletes a session by session ID.
func (p *FileProvider) Destory(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), os.ModePerm); err != nil {
return err
}
if err = ioutil.WriteFile(oldname, data, os.ModePerm); err != nil {
return err
}
}
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); 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{})
}

217
vendor/github.com/go-macaron/session/memory.go generated vendored Normal file
View 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
}
// Destory deletes a session by session ID.
func (p *MemProvider) Destory(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.Destory(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)})
}

235
vendor/github.com/go-macaron/session/redis/redis.go generated vendored Normal file
View file

@ -0,0 +1,235 @@
// 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"
"github.com/Unknwon/com"
"gopkg.in/ini.v1"
"gopkg.in/redis.v2"
"github.com/go-macaron/session"
)
// 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 {
data, err := session.EncodeGob(s.data)
if err != nil {
return err
}
return s.c.SetEx(s.prefix+s.sid, s.duration, string(data)).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).MustInt64()
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, "").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 {
has, err := p.c.Exists(p.prefix + sid).Result()
return err == nil && has
}
// Destory deletes a session by session ID.
func (p *RedisProvider) Destory(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.SetEx(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{})
}

View file

@ -0,0 +1 @@
ignore

399
vendor/github.com/go-macaron/session/session.go generated vendored Normal file
View file

@ -0,0 +1,399 @@
// 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"
"fmt"
"net/http"
"net/url"
"time"
"gopkg.in/macaron.v1"
)
const _VERSION = "0.3.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)
// Destory deletes a session.
Destory(*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
}
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)
}
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 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
// Destory deletes a session by session ID.
Destory(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))
}
// 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)
if len(sid) > 0 && 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) {
return m.provider.Read(sid)
}
// Destory deletes a session by given ID.
func (m *Manager) Destory(ctx *macaron.Context) error {
sid := ctx.GetCookie(m.opt.CookieName)
if len(sid) == 0 {
return nil
}
if err := m.provider.Destory(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)
sess, err = m.provider.Regenerate(oldsid, sid)
if err != nil {
return nil, err
}
ck := &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 {
ck.MaxAge = m.opt.CookieLifeTime
}
http.SetCookie(ctx.Resp, ck)
ctx.Req.AddCookie(ck)
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
}
// ___________.____ _____ _________ ___ ___
// \_ _____/| | / _ \ / _____// | \
// | __) | | / /_\ \ \_____ \/ ~ \
// | \ | |___/ | \/ \ Y /
// \___ / |_______ \____|__ /_______ /\___|_ /
// \/ \/ \/ \/ \/
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...)
}

60
vendor/github.com/go-macaron/session/utils.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
// 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
}
// 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)
}
return k
}

191
vendor/github.com/go-macaron/toolbox/LICENSE generated vendored Normal file
View file

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

110
vendor/github.com/go-macaron/toolbox/README.md generated vendored Normal file
View file

@ -0,0 +1,110 @@
toolbox
=======
Middleware toolbox provides health chcek, pprof, profile and statistic services for [Macaron](https://github.com/go-macaron/macaron).
[API Reference](https://gowalker.org/github.com/go-macaron/toolbox)
### Installation
go get github.com/go-macaron/toolbox
## Usage
```go
// main.go
import (
"gopkg.in/macaron.v1"
"github.com/go-macaron/toolbox"
)
func main() {
m := macaron.Classic()
m.Use(toolbox.Toolboxer(m))
m.Run()
}
```
Open your browser and visit `http://localhost:4000/debug` to see the effects.
## Options
`toolbox.Toolboxer` comes with a variety of configuration options:
```go
type dummyChecker struct {
}
func (dc *dummyChecker) Desc() string {
return "Dummy checker"
}
func (dc *dummyChecker) Check() error {
return nil
}
// ...
m.Use(toolbox.Toolboxer(m, toolbox.Options{
URLPrefix: "/debug", // URL prefix for toolbox dashboard.
HealthCheckURL: "/healthcheck", // URL for health check request.
HealthCheckers: []HealthChecker{
new(dummyChecker),
}, // Health checkers.
HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{
&toolbox.HealthCheckFuncDesc{
Desc: "Database connection",
Func: func() error { return "OK" },
},
}, // Health check functions.
PprofURLPrefix: "/debug/pprof/", // URL prefix of pprof.
ProfileURLPrefix: "/debug/profile/", // URL prefix of profile.
ProfilePath: "profile", // Path store profile files.
}))
// ...
```
## Route Statistic
Toolbox also comes with a route call statistic functionality:
```go
import (
"os"
"time"
//...
"github.com/go-macaron/toolbox"
)
func main() {
//...
m.Get("/", func(t toolbox.Toolbox) {
start := time.Now()
// Other operations.
t.AddStatistics("GET", "/", time.Since(start))
})
m.Get("/dump", func(t toolbox.Toolbox) {
t.GetMap(os.Stdout)
})
}
```
Output take from test:
```
+---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+
| Request URL | Method | Times | Total Used(s) | Max Used(μs) | Min Used(μs) | Avg Used(μs) |
+---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+
| /api/user | POST | 2 | 0.000122 | 120.000000 | 2.000000 | 61.000000 |
| /api/user | GET | 1 | 0.000013 | 13.000000 | 13.000000 | 13.000000 |
| /api/user | DELETE | 1 | 0.000001 | 1.400000 | 1.400000 | 1.400000 |
| /api/admin | POST | 1 | 0.000014 | 14.000000 | 14.000000 | 14.000000 |
| /api/user/unknwon | POST | 1 | 0.000012 | 12.000000 | 12.000000 | 12.000000 |
+---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+
```
## License
This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.

83
vendor/github.com/go-macaron/toolbox/healthcheck.go generated vendored Normal file
View file

@ -0,0 +1,83 @@
// 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 toolbox
import (
"bytes"
)
// HealthChecker represents a health check instance.
type HealthChecker interface {
Desc() string
Check() error
}
// HealthCheckFunc represents a callable function for health check.
type HealthCheckFunc func() error
// HealthCheckFunc represents a callable function for health check with description.
type HealthCheckFuncDesc struct {
Desc string
Func HealthCheckFunc
}
type healthCheck struct {
desc string
HealthChecker
check HealthCheckFunc // Not nil if add job as a function.
}
// AddHealthCheck adds new health check job.
func (t *toolbox) AddHealthCheck(hc HealthChecker) {
t.healthCheckJobs = append(t.healthCheckJobs, &healthCheck{
HealthChecker: hc,
})
}
// AddHealthCheckFunc adds a function as a new health check job.
func (t *toolbox) AddHealthCheckFunc(desc string, fn HealthCheckFunc) {
t.healthCheckJobs = append(t.healthCheckJobs, &healthCheck{
desc: desc,
check: fn,
})
}
func (t *toolbox) handleHealthCheck() string {
if len(t.healthCheckJobs) == 0 {
return "no health check jobs"
}
var buf bytes.Buffer
var err error
for _, job := range t.healthCheckJobs {
buf.WriteString("* ")
if job.check != nil {
buf.WriteString(job.desc)
err = job.check()
} else {
buf.WriteString(job.Desc())
err = job.Check()
}
buf.WriteString(": ")
if err == nil {
buf.WriteString("OK")
} else {
buf.WriteString(err.Error())
}
buf.WriteString("\n")
}
return buf.String()
}

163
vendor/github.com/go-macaron/toolbox/profile.go generated vendored Normal file
View file

@ -0,0 +1,163 @@
// 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 toolbox
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"path"
"runtime"
"runtime/debug"
"runtime/pprof"
"time"
"github.com/Unknwon/com"
"gopkg.in/macaron.v1"
)
var (
profilePath string
pid int
startTime = time.Now()
inCPUProfile bool
)
// StartCPUProfile starts CPU profile monitor.
func StartCPUProfile() error {
if inCPUProfile {
return errors.New("CPU profile has alreday been started!")
}
inCPUProfile = true
os.MkdirAll(profilePath, os.ModePerm)
f, err := os.Create(path.Join(profilePath, "cpu-"+com.ToStr(pid)+".pprof"))
if err != nil {
panic("fail to record CPU profile: " + err.Error())
}
pprof.StartCPUProfile(f)
return nil
}
// StopCPUProfile stops CPU profile monitor.
func StopCPUProfile() error {
if !inCPUProfile {
return errors.New("CPU profile hasn't been started!")
}
pprof.StopCPUProfile()
inCPUProfile = false
return nil
}
func init() {
pid = os.Getpid()
}
// DumpMemProf dumps memory profile in pprof.
func DumpMemProf(w io.Writer) {
pprof.WriteHeapProfile(w)
}
func dumpMemProf() {
os.MkdirAll(profilePath, os.ModePerm)
f, err := os.Create(path.Join(profilePath, "mem-"+com.ToStr(pid)+".memprof"))
if err != nil {
panic("fail to record memory profile: " + err.Error())
}
runtime.GC()
DumpMemProf(f)
f.Close()
}
func avg(items []time.Duration) time.Duration {
var sum time.Duration
for _, item := range items {
sum += item
}
return time.Duration(int64(sum) / int64(len(items)))
}
func dumpGC(memStats *runtime.MemStats, gcstats *debug.GCStats, w io.Writer) {
if gcstats.NumGC > 0 {
lastPause := gcstats.Pause[0]
elapsed := time.Now().Sub(startTime)
overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100
allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()
fmt.Fprintf(w, "NumGC:%d Pause:%s Pause(Avg):%s Overhead:%3.2f%% Alloc:%s Sys:%s Alloc(Rate):%s/s Histogram:%s %s %s \n",
gcstats.NumGC,
com.ToStr(lastPause),
com.ToStr(avg(gcstats.Pause)),
overhead,
com.HumaneFileSize(memStats.Alloc),
com.HumaneFileSize(memStats.Sys),
com.HumaneFileSize(uint64(allocatedRate)),
com.ToStr(gcstats.PauseQuantiles[94]),
com.ToStr(gcstats.PauseQuantiles[98]),
com.ToStr(gcstats.PauseQuantiles[99]))
} else {
// while GC has disabled
elapsed := time.Now().Sub(startTime)
allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()
fmt.Fprintf(w, "Alloc:%s Sys:%s Alloc(Rate):%s/s\n",
com.HumaneFileSize(memStats.Alloc),
com.HumaneFileSize(memStats.Sys),
com.HumaneFileSize(uint64(allocatedRate)))
}
}
// DumpGCSummary dumps GC information to io.Writer
func DumpGCSummary(w io.Writer) {
memStats := &runtime.MemStats{}
runtime.ReadMemStats(memStats)
gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}
debug.ReadGCStats(gcstats)
dumpGC(memStats, gcstats, w)
}
func handleProfile(ctx *macaron.Context) string {
switch ctx.Query("op") {
case "startcpu":
if err := StartCPUProfile(); err != nil {
return err.Error()
}
case "stopcpu":
if err := StopCPUProfile(); err != nil {
return err.Error()
}
case "mem":
dumpMemProf()
case "gc":
var buf bytes.Buffer
DumpGCSummary(&buf)
return string(buf.Bytes())
default:
return fmt.Sprintf(`<p>Available operations:</p>
<ol>
<li><a href="%[1]s?op=startcpu">Start CPU profile</a></li>
<li><a href="%[1]s?op=stopcpu">Stop CPU profile</a></li>
<li><a href="%[1]s?op=mem">Dump memory profile</a></li>
<li><a href="%[1]s?op=gc">Dump GC summary</a></li>
</ol>`, opt.ProfileURLPrefix)
}
ctx.Redirect(opt.ProfileURLPrefix)
return ""
}

138
vendor/github.com/go-macaron/toolbox/statistic.go generated vendored Normal file
View file

@ -0,0 +1,138 @@
// 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 toolbox
import (
"encoding/json"
"fmt"
"io"
"strings"
"sync"
"time"
)
// Statistics struct
type Statistics struct {
RequestUrl string
RequestNum int64
MinTime time.Duration
MaxTime time.Duration
TotalTime time.Duration
}
// UrlMap contains several statistics struct to log different data
type UrlMap struct {
lock sync.RWMutex
LengthLimit int // limit the urlmap's length if it's equal to 0 there's no limit
urlmap map[string]map[string]*Statistics
}
// add statistics task.
// it needs request method, request url and statistics time duration
func (m *UrlMap) AddStatistics(requestMethod, requestUrl string, requesttime time.Duration) {
m.lock.Lock()
defer m.lock.Unlock()
if method, ok := m.urlmap[requestUrl]; ok {
if s, ok := method[requestMethod]; ok {
s.RequestNum += 1
if s.MaxTime < requesttime {
s.MaxTime = requesttime
}
if s.MinTime > requesttime {
s.MinTime = requesttime
}
s.TotalTime += requesttime
} else {
nb := &Statistics{
RequestUrl: requestUrl,
RequestNum: 1,
MinTime: requesttime,
MaxTime: requesttime,
TotalTime: requesttime,
}
m.urlmap[requestUrl][requestMethod] = nb
}
} else {
if m.LengthLimit > 0 && m.LengthLimit <= len(m.urlmap) {
return
}
methodmap := make(map[string]*Statistics)
nb := &Statistics{
RequestUrl: requestUrl,
RequestNum: 1,
MinTime: requesttime,
MaxTime: requesttime,
TotalTime: requesttime,
}
methodmap[requestMethod] = nb
m.urlmap[requestUrl] = methodmap
}
}
// put url statistics result in io.Writer
func (m *UrlMap) GetMap(w io.Writer) {
m.lock.RLock()
defer m.lock.RUnlock()
sep := fmt.Sprintf("+%s+%s+%s+%s+%s+%s+%s+\n", strings.Repeat("-", 51), strings.Repeat("-", 12),
strings.Repeat("-", 18), strings.Repeat("-", 18), strings.Repeat("-", 18), strings.Repeat("-", 18), strings.Repeat("-", 18))
fmt.Fprintf(w, sep)
fmt.Fprintf(w, "| % -50s| % -10s | % -16s | % -16s | % -16s | % -16s | % -16s |\n", "Request URL", "Method", "Times", "Total Used(s)", "Max Used(μs)", "Min Used(μs)", "Avg Used(μs)")
fmt.Fprintf(w, sep)
for k, v := range m.urlmap {
for kk, vv := range v {
fmt.Fprintf(w, "| % -50s| % -10s | % 16d | % 16f | % 16.6f | % 16.6f | % 16.6f |\n", k,
kk, vv.RequestNum, vv.TotalTime.Seconds(), float64(vv.MaxTime.Nanoseconds())/1000,
float64(vv.MinTime.Nanoseconds())/1000, float64(time.Duration(int64(vv.TotalTime)/vv.RequestNum).Nanoseconds())/1000,
)
}
}
fmt.Fprintf(w, sep)
}
type URLMapInfo struct {
URL string `json:"url"`
Method string `json:"method"`
Times int64 `json:"times"`
TotalUsed float64 `json:"total_used"`
MaxUsed float64 `json:"max_used"`
MinUsed float64 `json:"min_used"`
AvgUsed float64 `json:"avg_used"`
}
func (m *UrlMap) JSON(w io.Writer) {
infos := make([]*URLMapInfo, 0, len(m.urlmap))
for k, v := range m.urlmap {
for kk, vv := range v {
infos = append(infos, &URLMapInfo{
URL: k,
Method: kk,
Times: vv.RequestNum,
TotalUsed: vv.TotalTime.Seconds(),
MaxUsed: float64(vv.MaxTime.Nanoseconds()) / 1000,
MinUsed: float64(vv.MinTime.Nanoseconds()) / 1000,
AvgUsed: float64(time.Duration(int64(vv.TotalTime)/vv.RequestNum).Nanoseconds()) / 1000,
})
}
}
if err := json.NewEncoder(w).Encode(infos); err != nil {
panic("URLMap.JSON: " + err.Error())
}
}

154
vendor/github.com/go-macaron/toolbox/toolbox.go generated vendored Normal file
View file

@ -0,0 +1,154 @@
// 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 toolbox is a middleware that provides health check, pprof, profile and statistic services for Macaron.
package toolbox
import (
"fmt"
"io"
"net/http"
"net/http/pprof"
"path"
"time"
"gopkg.in/macaron.v1"
)
const _VERSION = "0.1.2"
func Version() string {
return _VERSION
}
// Toolbox represents a tool box service for Macaron instance.
type Toolbox interface {
AddHealthCheck(HealthChecker)
AddHealthCheckFunc(string, HealthCheckFunc)
AddStatistics(string, string, time.Duration)
GetMap(io.Writer)
JSON(io.Writer)
}
type toolbox struct {
*UrlMap
healthCheckJobs []*healthCheck
}
// Options represents a struct for specifying configuration options for the Toolbox middleware.
type Options struct {
// URL prefix for toolbox dashboard. Default is "/debug".
URLPrefix string
// URL for health check request. Default is "/healthcheck".
HealthCheckURL string
// Health checkers.
HealthCheckers []HealthChecker
// Health check functions.
HealthCheckFuncs []*HealthCheckFuncDesc
// URL for URL map json. Default is "/urlmap.json".
URLMapPrefix string
// URL prefix of pprof. Default is "/debug/pprof/".
PprofURLPrefix string
// URL prefix of profile. Default is "/debug/profile/".
ProfileURLPrefix string
// Path store profile files. Default is "profile".
ProfilePath string
}
var opt Options
func prepareOptions(options []Options) {
if len(options) > 0 {
opt = options[0]
}
// Defaults.
if len(opt.URLPrefix) == 0 {
opt.URLPrefix = "/debug"
}
if len(opt.HealthCheckURL) == 0 {
opt.HealthCheckURL = "/healthcheck"
}
if len(opt.URLMapPrefix) == 0 {
opt.URLMapPrefix = "/urlmap.json"
}
if len(opt.PprofURLPrefix) == 0 {
opt.PprofURLPrefix = "/debug/pprof/"
} else if opt.PprofURLPrefix[len(opt.PprofURLPrefix)-1] != '/' {
opt.PprofURLPrefix += "/"
}
if len(opt.ProfileURLPrefix) == 0 {
opt.ProfileURLPrefix = "/debug/profile/"
} else if opt.ProfileURLPrefix[len(opt.ProfileURLPrefix)-1] != '/' {
opt.ProfileURLPrefix += "/"
}
if len(opt.ProfilePath) == 0 {
opt.ProfilePath = path.Join(macaron.Root, "profile")
}
}
func dashboard(ctx *macaron.Context) string {
return fmt.Sprintf(`<p>Toolbox Index:</p>
<ol>
<li><a href="%s">Pprof Information</a></li>
<li><a href="%s">Profile Operations</a></li>
</ol>`, opt.PprofURLPrefix, opt.ProfileURLPrefix)
}
var _ Toolbox = &toolbox{}
// Toolboxer is a middleware provides health check, pprof, profile and statistic services for your application.
func Toolboxer(m *macaron.Macaron, options ...Options) macaron.Handler {
prepareOptions(options)
t := &toolbox{
healthCheckJobs: make([]*healthCheck, 0, len(opt.HealthCheckers)+len(opt.HealthCheckFuncs)),
}
// Dashboard.
m.Get(opt.URLPrefix, dashboard)
// Health check.
for _, hc := range opt.HealthCheckers {
t.AddHealthCheck(hc)
}
for _, fd := range opt.HealthCheckFuncs {
t.AddHealthCheckFunc(fd.Desc, fd.Func)
}
m.Get(opt.HealthCheckURL, t.handleHealthCheck)
// URL map.
m.Get(opt.URLMapPrefix, func(rw http.ResponseWriter) {
t.JSON(rw)
})
// Pprof.
m.Any(path.Join(opt.PprofURLPrefix, "cmdline"), pprof.Cmdline)
m.Any(path.Join(opt.PprofURLPrefix, "profile"), pprof.Profile)
m.Any(path.Join(opt.PprofURLPrefix, "symbol"), pprof.Symbol)
m.Any(opt.PprofURLPrefix, pprof.Index)
m.Any(path.Join(opt.PprofURLPrefix, "*"), pprof.Index)
// Profile.
profilePath = opt.ProfilePath
m.Get(opt.ProfileURLPrefix, handleProfile)
// Routes statistic.
t.UrlMap = &UrlMap{
urlmap: make(map[string]map[string]*Statistics),
}
return func(ctx *macaron.Context) {
ctx.MapTo(t, (*Toolbox)(nil))
}
}