mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Added all required dependencies
This commit is contained in:
		
							
								
								
									
										191
									
								
								vendor/github.com/go-macaron/binding/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/binding/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										20
									
								
								vendor/github.com/go-macaron/binding/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/go-macaron/binding/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # binding [](https://travis-ci.org/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
									
								
							
							
						
						
									
										669
									
								
								vendor/github.com/go-macaron/binding/binding.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?`) | ||||
| ) | ||||
|  | ||||
| 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
									
								
							
							
						
						
									
										159
									
								
								vendor/github.com/go-macaron/binding/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| // Copyright 2014 Martini Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package binding | ||||
|  | ||||
| const ( | ||||
| 	// Type mismatch errors. | ||||
| 	ERR_CONTENT_TYPE    = "ContentTypeError" | ||||
| 	ERR_DESERIALIZATION = "DeserializationError" | ||||
| 	ERR_INTERGER_TYPE   = "IntegerTypeError" | ||||
| 	ERR_BOOLEAN_TYPE    = "BooleanTypeError" | ||||
| 	ERR_FLOAT_TYPE      = "FloatTypeError" | ||||
|  | ||||
| 	// Validation errors. | ||||
| 	ERR_REQUIRED       = "RequiredError" | ||||
| 	ERR_ALPHA_DASH     = "AlphaDashError" | ||||
| 	ERR_ALPHA_DASH_DOT = "AlphaDashDotError" | ||||
| 	ERR_SIZE           = "SizeError" | ||||
| 	ERR_MIN_SIZE       = "MinSizeError" | ||||
| 	ERR_MAX_SIZE       = "MaxSizeError" | ||||
| 	ERR_RANGE          = "RangeError" | ||||
| 	ERR_EMAIL          = "EmailError" | ||||
| 	ERR_URL            = "UrlError" | ||||
| 	ERR_IN             = "InError" | ||||
| 	ERR_NOT_INT        = "NotInError" | ||||
| 	ERR_INCLUDE        = "IncludeError" | ||||
| 	ERR_EXCLUDE        = "ExcludeError" | ||||
| 	ERR_DEFAULT        = "DefaultError" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| 	// Errors may be generated during deserialization, binding, | ||||
| 	// or validation. This type is mapped to the context so you | ||||
| 	// can inject it into your own handlers and use it in your | ||||
| 	// application if you want all your errors to look the same. | ||||
| 	Errors []Error | ||||
|  | ||||
| 	Error struct { | ||||
| 		// An error supports zero or more field names, because an | ||||
| 		// error can morph three ways: (1) it can indicate something | ||||
| 		// wrong with the request as a whole, (2) it can point to a | ||||
| 		// specific problem with a particular input field, or (3) it | ||||
| 		// can span multiple related input fields. | ||||
| 		FieldNames []string `json:"fieldNames,omitempty"` | ||||
|  | ||||
| 		// The classification is like an error code, convenient to | ||||
| 		// use when processing or categorizing an error programmatically. | ||||
| 		// It may also be called the "kind" of error. | ||||
| 		Classification string `json:"classification,omitempty"` | ||||
|  | ||||
| 		// Message should be human-readable and detailed enough to | ||||
| 		// pinpoint and resolve the problem, but it should be brief. For | ||||
| 		// example, a payload of 100 objects in a JSON array might have | ||||
| 		// an error in the 41st object. The message should help the | ||||
| 		// end user find and fix the error with their request. | ||||
| 		Message string `json:"message,omitempty"` | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| // Add adds an error associated with the fields indicated | ||||
| // by fieldNames, with the given classification and message. | ||||
| func (e *Errors) Add(fieldNames []string, classification, message string) { | ||||
| 	*e = append(*e, Error{ | ||||
| 		FieldNames:     fieldNames, | ||||
| 		Classification: classification, | ||||
| 		Message:        message, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // Len returns the number of errors. | ||||
| func (e *Errors) Len() int { | ||||
| 	return len(*e) | ||||
| } | ||||
|  | ||||
| // Has determines whether an Errors slice has an Error with | ||||
| // a given classification in it; it does not search on messages | ||||
| // or field names. | ||||
| func (e *Errors) Has(class string) bool { | ||||
| 	for _, err := range *e { | ||||
| 		if err.Kind() == class { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| /* | ||||
| // WithClass gets a copy of errors that are classified by the | ||||
| // the given classification. | ||||
| func (e *Errors) WithClass(classification string) Errors { | ||||
| 	var errs Errors | ||||
| 	for _, err := range *e { | ||||
| 		if err.Kind() == classification { | ||||
| 			errs = append(errs, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return errs | ||||
| } | ||||
|  | ||||
| // ForField gets a copy of errors that are associated with the | ||||
| // field by the given name. | ||||
| func (e *Errors) ForField(name string) Errors { | ||||
| 	var errs Errors | ||||
| 	for _, err := range *e { | ||||
| 		for _, fieldName := range err.Fields() { | ||||
| 			if fieldName == name { | ||||
| 				errs = append(errs, err) | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return errs | ||||
| } | ||||
|  | ||||
| // Get gets errors of a particular class for the specified | ||||
| // field name. | ||||
| func (e *Errors) Get(class, fieldName string) Errors { | ||||
| 	var errs Errors | ||||
| 	for _, err := range *e { | ||||
| 		if err.Kind() == class { | ||||
| 			for _, nameOfField := range err.Fields() { | ||||
| 				if nameOfField == fieldName { | ||||
| 					errs = append(errs, err) | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return errs | ||||
| } | ||||
| */ | ||||
|  | ||||
| // Fields returns the list of field names this error is | ||||
| // associated with. | ||||
| func (e Error) Fields() []string { | ||||
| 	return e.FieldNames | ||||
| } | ||||
|  | ||||
| // Kind returns this error's classification. | ||||
| func (e Error) Kind() string { | ||||
| 	return e.Classification | ||||
| } | ||||
|  | ||||
| // Error returns this error's message. | ||||
| func (e Error) Error() string { | ||||
| 	return e.Message | ||||
| } | ||||
							
								
								
									
										191
									
								
								vendor/github.com/go-macaron/cache/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/cache/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										20
									
								
								vendor/github.com/go-macaron/cache/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/go-macaron/cache/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # cache [](https://travis-ci.org/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
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/go-macaron/cache/cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| // Package cache is a middleware that provides the cache management of Macaron. | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"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
									
								
							
							
						
						
									
										208
									
								
								vendor/github.com/go-macaron/cache/file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"crypto/md5" | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"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()) | ||||
| } | ||||
							
								
								
									
										92
									
								
								vendor/github.com/go-macaron/cache/memcache/memcache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/go-macaron/cache/memcache/memcache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/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{}) | ||||
| } | ||||
							
								
								
									
										1
									
								
								vendor/github.com/go-macaron/cache/memcache/memcache.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/go-macaron/cache/memcache/memcache.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ignore | ||||
							
								
								
									
										179
									
								
								vendor/github.com/go-macaron/cache/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/github.com/go-macaron/cache/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // MemoryItem represents a memory cache item. | ||||
| type MemoryItem struct { | ||||
| 	val     interface{} | ||||
| 	created int64 | ||||
| 	expire  int64 | ||||
| } | ||||
|  | ||||
| func (item *MemoryItem) hasExpired() bool { | ||||
| 	return item.expire > 0 && | ||||
| 		(time.Now().Unix()-item.created) >= item.expire | ||||
| } | ||||
|  | ||||
| // MemoryCacher represents a memory cache adapter implementation. | ||||
| type MemoryCacher struct { | ||||
| 	lock     sync.RWMutex | ||||
| 	items    map[string]*MemoryItem | ||||
| 	interval int // GC interval. | ||||
| } | ||||
|  | ||||
| // NewMemoryCacher creates and returns a new memory cacher. | ||||
| func NewMemoryCacher() *MemoryCacher { | ||||
| 	return &MemoryCacher{items: make(map[string]*MemoryItem)} | ||||
| } | ||||
|  | ||||
| // Put puts value into cache with key and expire time. | ||||
| // If expired is 0, it will be deleted by next GC operation. | ||||
| func (c *MemoryCacher) Put(key string, val interface{}, expire int64) error { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
|  | ||||
| 	c.items[key] = &MemoryItem{ | ||||
| 		val:     val, | ||||
| 		created: time.Now().Unix(), | ||||
| 		expire:  expire, | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Get gets cached value by given key. | ||||
| func (c *MemoryCacher) Get(key string) interface{} { | ||||
| 	c.lock.RLock() | ||||
| 	defer c.lock.RUnlock() | ||||
|  | ||||
| 	item, ok := c.items[key] | ||||
| 	if !ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if item.hasExpired() { | ||||
| 		go c.Delete(key) | ||||
| 		return nil | ||||
| 	} | ||||
| 	return item.val | ||||
| } | ||||
|  | ||||
| // Delete deletes cached value by given key. | ||||
| func (c *MemoryCacher) Delete(key string) error { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
|  | ||||
| 	delete(c.items, key) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Incr increases cached int-type value by given key as a counter. | ||||
| func (c *MemoryCacher) Incr(key string) (err error) { | ||||
| 	c.lock.RLock() | ||||
| 	defer c.lock.RUnlock() | ||||
|  | ||||
| 	item, ok := c.items[key] | ||||
| 	if !ok { | ||||
| 		return errors.New("key not exist") | ||||
| 	} | ||||
| 	item.val, err = Incr(item.val) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // Decr decreases cached int-type value by given key as a counter. | ||||
| func (c *MemoryCacher) Decr(key string) (err error) { | ||||
| 	c.lock.RLock() | ||||
| 	defer c.lock.RUnlock() | ||||
|  | ||||
| 	item, ok := c.items[key] | ||||
| 	if !ok { | ||||
| 		return errors.New("key not exist") | ||||
| 	} | ||||
|  | ||||
| 	item.val, err = Decr(item.val) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // IsExist returns true if cached value exists. | ||||
| func (c *MemoryCacher) IsExist(key string) bool { | ||||
| 	c.lock.RLock() | ||||
| 	defer c.lock.RUnlock() | ||||
|  | ||||
| 	_, ok := c.items[key] | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // Flush deletes all cached data. | ||||
| func (c *MemoryCacher) Flush() error { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
|  | ||||
| 	c.items = make(map[string]*MemoryItem) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *MemoryCacher) checkRawExpiration(key string) { | ||||
| 	item, ok := c.items[key] | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if item.hasExpired() { | ||||
| 		delete(c.items, key) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *MemoryCacher) checkExpiration(key string) { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
|  | ||||
| 	c.checkRawExpiration(key) | ||||
| } | ||||
|  | ||||
| func (c *MemoryCacher) startGC() { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
|  | ||||
| 	if c.interval < 1 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if c.items != nil { | ||||
| 		for key, _ := range c.items { | ||||
| 			c.checkRawExpiration(key) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	time.AfterFunc(time.Duration(c.interval)*time.Second, func() { c.startGC() }) | ||||
| } | ||||
|  | ||||
| // StartAndGC starts GC routine based on config string settings. | ||||
| func (c *MemoryCacher) StartAndGC(opt Options) error { | ||||
| 	c.lock.Lock() | ||||
| 	c.interval = opt.Interval | ||||
| 	c.lock.Unlock() | ||||
|  | ||||
| 	go c.startGC() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	Register("memory", NewMemoryCacher()) | ||||
| } | ||||
							
								
								
									
										178
									
								
								vendor/github.com/go-macaron/cache/redis/redis.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								vendor/github.com/go-macaron/cache/redis/redis.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/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{}) | ||||
| } | ||||
							
								
								
									
										1
									
								
								vendor/github.com/go-macaron/cache/redis/redis.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/go-macaron/cache/redis/redis.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ignore | ||||
							
								
								
									
										84
									
								
								vendor/github.com/go-macaron/cache/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/go-macaron/cache/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/gob" | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| func EncodeGob(item *Item) ([]byte, error) { | ||||
| 	buf := bytes.NewBuffer(nil) | ||||
| 	err := gob.NewEncoder(buf).Encode(item) | ||||
| 	return buf.Bytes(), err | ||||
| } | ||||
|  | ||||
| func DecodeGob(data []byte, out *Item) error { | ||||
| 	buf := bytes.NewBuffer(data) | ||||
| 	return gob.NewDecoder(buf).Decode(&out) | ||||
| } | ||||
|  | ||||
| func Incr(val interface{}) (interface{}, error) { | ||||
| 	switch val.(type) { | ||||
| 	case int: | ||||
| 		val = val.(int) + 1 | ||||
| 	case int32: | ||||
| 		val = val.(int32) + 1 | ||||
| 	case int64: | ||||
| 		val = val.(int64) + 1 | ||||
| 	case uint: | ||||
| 		val = val.(uint) + 1 | ||||
| 	case uint32: | ||||
| 		val = val.(uint32) + 1 | ||||
| 	case uint64: | ||||
| 		val = val.(uint64) + 1 | ||||
| 	default: | ||||
| 		return val, errors.New("item value is not int-type") | ||||
| 	} | ||||
| 	return val, nil | ||||
| } | ||||
|  | ||||
| func Decr(val interface{}) (interface{}, error) { | ||||
| 	switch val.(type) { | ||||
| 	case int: | ||||
| 		val = val.(int) - 1 | ||||
| 	case int32: | ||||
| 		val = val.(int32) - 1 | ||||
| 	case int64: | ||||
| 		val = val.(int64) - 1 | ||||
| 	case uint: | ||||
| 		if val.(uint) > 0 { | ||||
| 			val = val.(uint) - 1 | ||||
| 		} else { | ||||
| 			return val, errors.New("item value is less than 0") | ||||
| 		} | ||||
| 	case uint32: | ||||
| 		if val.(uint32) > 0 { | ||||
| 			val = val.(uint32) - 1 | ||||
| 		} else { | ||||
| 			return val, errors.New("item value is less than 0") | ||||
| 		} | ||||
| 	case uint64: | ||||
| 		if val.(uint64) > 0 { | ||||
| 			val = val.(uint64) - 1 | ||||
| 		} else { | ||||
| 			return val, errors.New("item value is less than 0") | ||||
| 		} | ||||
| 	default: | ||||
| 		return val, errors.New("item value is not int-type") | ||||
| 	} | ||||
| 	return val, nil | ||||
| } | ||||
							
								
								
									
										191
									
								
								vendor/github.com/go-macaron/captcha/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/captcha/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										16
									
								
								vendor/github.com/go-macaron/captcha/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/go-macaron/captcha/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| # captcha [](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
									
								
							
							
						
						
									
										241
									
								
								vendor/github.com/go-macaron/captcha/captcha.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										498
									
								
								vendor/github.com/go-macaron/captcha/image.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										277
									
								
								vendor/github.com/go-macaron/captcha/siprng.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package captcha | ||||
|  | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"encoding/binary" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| // siprng is PRNG based on SipHash-2-4. | ||||
| type siprng struct { | ||||
| 	mu          sync.Mutex | ||||
| 	k0, k1, ctr uint64 | ||||
| } | ||||
|  | ||||
| // siphash implements SipHash-2-4, accepting a uint64 as a message. | ||||
| func siphash(k0, k1, m uint64) uint64 { | ||||
| 	// Initialization. | ||||
| 	v0 := k0 ^ 0x736f6d6570736575 | ||||
| 	v1 := k1 ^ 0x646f72616e646f6d | ||||
| 	v2 := k0 ^ 0x6c7967656e657261 | ||||
| 	v3 := k1 ^ 0x7465646279746573 | ||||
| 	t := uint64(8) << 56 | ||||
|  | ||||
| 	// Compression. | ||||
| 	v3 ^= m | ||||
|  | ||||
| 	// Round 1. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	// Round 2. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	v0 ^= m | ||||
|  | ||||
| 	// Compress last block. | ||||
| 	v3 ^= t | ||||
|  | ||||
| 	// Round 1. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	// Round 2. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	v0 ^= t | ||||
|  | ||||
| 	// Finalization. | ||||
| 	v2 ^= 0xff | ||||
|  | ||||
| 	// Round 1. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	// Round 2. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	// Round 3. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	// Round 4. | ||||
| 	v0 += v1 | ||||
| 	v1 = v1<<13 | v1>>(64-13) | ||||
| 	v1 ^= v0 | ||||
| 	v0 = v0<<32 | v0>>(64-32) | ||||
|  | ||||
| 	v2 += v3 | ||||
| 	v3 = v3<<16 | v3>>(64-16) | ||||
| 	v3 ^= v2 | ||||
|  | ||||
| 	v0 += v3 | ||||
| 	v3 = v3<<21 | v3>>(64-21) | ||||
| 	v3 ^= v0 | ||||
|  | ||||
| 	v2 += v1 | ||||
| 	v1 = v1<<17 | v1>>(64-17) | ||||
| 	v1 ^= v2 | ||||
| 	v2 = v2<<32 | v2>>(64-32) | ||||
|  | ||||
| 	return v0 ^ v1 ^ v2 ^ v3 | ||||
| } | ||||
|  | ||||
| // rekey sets a new PRNG key, which is read from crypto/rand. | ||||
| func (p *siprng) rekey() { | ||||
| 	var k [16]byte | ||||
| 	if _, err := io.ReadFull(rand.Reader, k[:]); err != nil { | ||||
| 		panic(err.Error()) | ||||
| 	} | ||||
| 	p.k0 = binary.LittleEndian.Uint64(k[0:8]) | ||||
| 	p.k1 = binary.LittleEndian.Uint64(k[8:16]) | ||||
| 	p.ctr = 1 | ||||
| } | ||||
|  | ||||
| // Uint64 returns a new pseudorandom uint64. | ||||
| // It rekeys PRNG on the first call and every 64 MB of generated data. | ||||
| func (p *siprng) Uint64() uint64 { | ||||
| 	p.mu.Lock() | ||||
| 	if p.ctr == 0 || p.ctr > 8*1024*1024 { | ||||
| 		p.rekey() | ||||
| 	} | ||||
| 	v := siphash(p.k0, p.k1, p.ctr) | ||||
| 	p.ctr++ | ||||
| 	p.mu.Unlock() | ||||
| 	return v | ||||
| } | ||||
|  | ||||
| func (p *siprng) Int63() int64 { | ||||
| 	return int64(p.Uint64() & 0x7fffffffffffffff) | ||||
| } | ||||
|  | ||||
| func (p *siprng) Uint32() uint32 { | ||||
| 	return uint32(p.Uint64()) | ||||
| } | ||||
|  | ||||
| func (p *siprng) Int31() int32 { | ||||
| 	return int32(p.Uint32() & 0x7fffffff) | ||||
| } | ||||
|  | ||||
| func (p *siprng) Intn(n int) int { | ||||
| 	if n <= 0 { | ||||
| 		panic("invalid argument to Intn") | ||||
| 	} | ||||
| 	if n <= 1<<31-1 { | ||||
| 		return int(p.Int31n(int32(n))) | ||||
| 	} | ||||
| 	return int(p.Int63n(int64(n))) | ||||
| } | ||||
|  | ||||
| func (p *siprng) Int63n(n int64) int64 { | ||||
| 	if n <= 0 { | ||||
| 		panic("invalid argument to Int63n") | ||||
| 	} | ||||
| 	max := int64((1 << 63) - 1 - (1<<63)%uint64(n)) | ||||
| 	v := p.Int63() | ||||
| 	for v > max { | ||||
| 		v = p.Int63() | ||||
| 	} | ||||
| 	return v % n | ||||
| } | ||||
|  | ||||
| func (p *siprng) Int31n(n int32) int32 { | ||||
| 	if n <= 0 { | ||||
| 		panic("invalid argument to Int31n") | ||||
| 	} | ||||
| 	max := int32((1 << 31) - 1 - (1<<31)%uint32(n)) | ||||
| 	v := p.Int31() | ||||
| 	for v > max { | ||||
| 		v = p.Int31() | ||||
| 	} | ||||
| 	return v % n | ||||
| } | ||||
|  | ||||
| func (p *siprng) Float64() float64 { return float64(p.Int63()) / (1 << 63) } | ||||
							
								
								
									
										191
									
								
								vendor/github.com/go-macaron/csrf/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/csrf/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										18
									
								
								vendor/github.com/go-macaron/csrf/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/go-macaron/csrf/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| # csrf [](https://travis-ci.org/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
									
								
							
							
						
						
									
										251
									
								
								vendor/github.com/go-macaron/csrf/csrf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/go-macaron/csrf/xsrf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| // Copyright 2012 Google Inc. All Rights Reserved. | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package csrf | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/subtle" | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // The duration that XSRF tokens are valid. | ||||
| // It is exported so clients may set cookie timeouts that match generated tokens. | ||||
| const TIMEOUT = 24 * time.Hour | ||||
|  | ||||
| // clean sanitizes a string for inclusion in a token by replacing all ":"s. | ||||
| func clean(s string) string { | ||||
| 	return strings.Replace(s, ":", "_", -1) | ||||
| } | ||||
|  | ||||
| // GenerateToken returns a URL-safe secure XSRF token that expires in 24 hours. | ||||
| // | ||||
| // key is a secret key for your application. | ||||
| // userID is a unique identifier for the user. | ||||
| // actionID is the action the user is taking (e.g. POSTing to a particular path). | ||||
| func GenerateToken(key, userID, actionID string) string { | ||||
| 	return generateTokenAtTime(key, userID, actionID, time.Now()) | ||||
| } | ||||
|  | ||||
| // generateTokenAtTime is like Generate, but returns a token that expires 24 hours from now. | ||||
| func generateTokenAtTime(key, userID, actionID string, now time.Time) string { | ||||
| 	h := hmac.New(sha1.New, []byte(key)) | ||||
| 	fmt.Fprintf(h, "%s:%s:%d", clean(userID), clean(actionID), now.UnixNano()) | ||||
| 	tok := fmt.Sprintf("%s:%d", h.Sum(nil), now.UnixNano()) | ||||
| 	return base64.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
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/gzip/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										20
									
								
								vendor/github.com/go-macaron/gzip/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/go-macaron/gzip/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # gzip [](https://travis-ci.org/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
									
								
							
							
						
						
									
										121
									
								
								vendor/github.com/go-macaron/gzip/gzip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/i18n/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										16
									
								
								vendor/github.com/go-macaron/i18n/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/go-macaron/i18n/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| # i18n [](https://travis-ci.org/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
									
								
							
							
						
						
									
										225
									
								
								vendor/github.com/go-macaron/i18n/i18n.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/inject/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										11
									
								
								vendor/github.com/go-macaron/inject/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/go-macaron/inject/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # inject [](https://travis-ci.org/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
									
								
							
							
						
						
									
										262
									
								
								vendor/github.com/go-macaron/inject/inject.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,262 @@ | ||||
| // Copyright 2013 Jeremy Saenz | ||||
| // Copyright 2015 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| // Package inject provides utilities for mapping and injecting dependencies in various ways. | ||||
| package inject | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| ) | ||||
|  | ||||
| // Injector represents an interface for mapping and injecting dependencies into structs | ||||
| // and function arguments. | ||||
| type Injector interface { | ||||
| 	Applicator | ||||
| 	Invoker | ||||
| 	TypeMapper | ||||
| 	// SetParent sets the parent of the injector. If the injector cannot find a | ||||
| 	// dependency in its Type map it will check its parent before returning an | ||||
| 	// error. | ||||
| 	SetParent(Injector) | ||||
| } | ||||
|  | ||||
| // Applicator represents an interface for mapping dependencies to a struct. | ||||
| type Applicator interface { | ||||
| 	// Maps dependencies in the Type map to each field in the struct | ||||
| 	// that is tagged with 'inject'. Returns an error if the injection | ||||
| 	// fails. | ||||
| 	Apply(interface{}) error | ||||
| } | ||||
|  | ||||
| // Invoker represents an interface for calling functions via reflection. | ||||
| type Invoker interface { | ||||
| 	// Invoke attempts to call the interface{} provided as a function, | ||||
| 	// providing dependencies for function arguments based on Type. Returns | ||||
| 	// a slice of reflect.Value representing the returned values of the function. | ||||
| 	// Returns an error if the injection fails. | ||||
| 	Invoke(interface{}) ([]reflect.Value, error) | ||||
| } | ||||
|  | ||||
| // FastInvoker represents an interface in order to avoid the calling function via reflection. | ||||
| // | ||||
| // example: | ||||
| //	type handlerFuncHandler func(http.ResponseWriter, *http.Request) error | ||||
| //	func (f handlerFuncHandler)Invoke([]interface{}) ([]reflect.Value, error){ | ||||
| //		ret := f(p[0].(http.ResponseWriter), p[1].(*http.Request)) | ||||
| //		return []reflect.Value{reflect.ValueOf(ret)}, nil | ||||
| //	} | ||||
| // | ||||
| //	type funcHandler func(int, string) | ||||
| //	func (f funcHandler)Invoke([]interface{}) ([]reflect.Value, error){ | ||||
| //		f(p[0].(int), p[1].(string)) | ||||
| //		return nil, nil | ||||
| //	} | ||||
| type FastInvoker interface { | ||||
| 	// Invoke attempts to call the ordinary functions. If f is a function | ||||
| 	// with the appropriate signature, f.Invoke([]interface{}) is a Call that calls f. | ||||
| 	// Returns a slice of reflect.Value representing the returned values of the function. | ||||
| 	// Returns an error if the injection fails. | ||||
| 	Invoke([]interface{}) ([]reflect.Value, error) | ||||
| } | ||||
|  | ||||
| // IsFastInvoker check interface is FastInvoker | ||||
| func IsFastInvoker(h interface{}) bool { | ||||
| 	_, ok := h.(FastInvoker) | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // TypeMapper represents an interface for mapping interface{} values based on type. | ||||
| type TypeMapper interface { | ||||
| 	// Maps the interface{} value based on its immediate type from reflect.TypeOf. | ||||
| 	Map(interface{}) TypeMapper | ||||
| 	// Maps the interface{} value based on the pointer of an Interface provided. | ||||
| 	// This is really only useful for mapping a value as an interface, as interfaces | ||||
| 	// cannot at this time be referenced directly without a pointer. | ||||
| 	MapTo(interface{}, interface{}) TypeMapper | ||||
| 	// Provides a possibility to directly insert a mapping based on type and value. | ||||
| 	// This makes it possible to directly map type arguments not possible to instantiate | ||||
| 	// with reflect like unidirectional channels. | ||||
| 	Set(reflect.Type, reflect.Value) TypeMapper | ||||
| 	// Returns the Value that is mapped to the current type. Returns a zeroed Value if | ||||
| 	// the Type has not been mapped. | ||||
| 	GetVal(reflect.Type) reflect.Value | ||||
| } | ||||
|  | ||||
| type injector struct { | ||||
| 	values map[reflect.Type]reflect.Value | ||||
| 	parent Injector | ||||
| } | ||||
|  | ||||
| // InterfaceOf dereferences a pointer to an Interface type. | ||||
| // It panics if value is not an pointer to an interface. | ||||
| func InterfaceOf(value interface{}) reflect.Type { | ||||
| 	t := reflect.TypeOf(value) | ||||
|  | ||||
| 	for t.Kind() == reflect.Ptr { | ||||
| 		t = t.Elem() | ||||
| 	} | ||||
|  | ||||
| 	if t.Kind() != reflect.Interface { | ||||
| 		panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)") | ||||
| 	} | ||||
|  | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| // New returns a new Injector. | ||||
| func New() Injector { | ||||
| 	return &injector{ | ||||
| 		values: make(map[reflect.Type]reflect.Value), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Invoke attempts to call the interface{} provided as a function, | ||||
| // providing dependencies for function arguments based on Type. | ||||
| // Returns a slice of reflect.Value representing the returned values of the function. | ||||
| // Returns an error if the injection fails. | ||||
| // It panics if f is not a function | ||||
| func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) { | ||||
| 	t := reflect.TypeOf(f) | ||||
| 	switch v := f.(type) { | ||||
| 	case FastInvoker: | ||||
| 		return inj.fastInvoke(v, t, t.NumIn()) | ||||
| 	default: | ||||
| 		return inj.callInvoke(f, t, t.NumIn()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (inj *injector) fastInvoke(f FastInvoker, t reflect.Type, numIn int) ([]reflect.Value, error) { | ||||
| 	var in []interface{} | ||||
| 	if numIn > 0 { | ||||
| 		in = make([]interface{}, numIn) // Panic if t is not kind of Func | ||||
| 		var argType reflect.Type | ||||
| 		var val reflect.Value | ||||
| 		for i := 0; i < numIn; i++ { | ||||
| 			argType = t.In(i) | ||||
| 			val = inj.GetVal(argType) | ||||
| 			if !val.IsValid() { | ||||
| 				return nil, fmt.Errorf("Value not found for type %v", argType) | ||||
| 			} | ||||
|  | ||||
| 			in[i] = val.Interface() | ||||
| 		} | ||||
| 	} | ||||
| 	return f.Invoke(in) | ||||
| } | ||||
|  | ||||
| // callInvoke reflect.Value.Call | ||||
| func (inj *injector) callInvoke(f interface{}, t reflect.Type, numIn int) ([]reflect.Value, error) { | ||||
| 	var in []reflect.Value | ||||
| 	if numIn > 0 { | ||||
| 		in = make([]reflect.Value, numIn) | ||||
| 		var argType reflect.Type | ||||
| 		var val reflect.Value | ||||
| 		for i := 0; i < numIn; i++ { | ||||
| 			argType = t.In(i) | ||||
| 			val = inj.GetVal(argType) | ||||
| 			if !val.IsValid() { | ||||
| 				return nil, fmt.Errorf("Value not found for type %v", argType) | ||||
| 			} | ||||
|  | ||||
| 			in[i] = val | ||||
| 		} | ||||
| 	} | ||||
| 	return reflect.ValueOf(f).Call(in), nil | ||||
| } | ||||
|  | ||||
| // Maps dependencies in the Type map to each field in the struct | ||||
| // that is tagged with 'inject'. | ||||
| // Returns an error if the injection fails. | ||||
| func (inj *injector) Apply(val interface{}) error { | ||||
| 	v := reflect.ValueOf(val) | ||||
|  | ||||
| 	for v.Kind() == reflect.Ptr { | ||||
| 		v = v.Elem() | ||||
| 	} | ||||
|  | ||||
| 	if v.Kind() != reflect.Struct { | ||||
| 		return nil // Should not panic here ? | ||||
| 	} | ||||
|  | ||||
| 	t := v.Type() | ||||
|  | ||||
| 	for i := 0; i < v.NumField(); i++ { | ||||
| 		f := v.Field(i) | ||||
| 		structField := t.Field(i) | ||||
| 		if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") { | ||||
| 			ft := f.Type() | ||||
| 			v := inj.GetVal(ft) | ||||
| 			if !v.IsValid() { | ||||
| 				return fmt.Errorf("Value not found for type %v", ft) | ||||
| 			} | ||||
|  | ||||
| 			f.Set(v) | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Maps the concrete value of val to its dynamic type using reflect.TypeOf, | ||||
| // It returns the TypeMapper registered in. | ||||
| func (i *injector) Map(val interface{}) TypeMapper { | ||||
| 	i.values[reflect.TypeOf(val)] = reflect.ValueOf(val) | ||||
| 	return i | ||||
| } | ||||
|  | ||||
| func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper { | ||||
| 	i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val) | ||||
| 	return i | ||||
| } | ||||
|  | ||||
| // Maps the given reflect.Type to the given reflect.Value and returns | ||||
| // the Typemapper the mapping has been registered in. | ||||
| func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper { | ||||
| 	i.values[typ] = val | ||||
| 	return i | ||||
| } | ||||
|  | ||||
| func (i *injector) GetVal(t reflect.Type) reflect.Value { | ||||
| 	val := i.values[t] | ||||
|  | ||||
| 	if val.IsValid() { | ||||
| 		return val | ||||
| 	} | ||||
|  | ||||
| 	// no concrete types found, try to find implementors | ||||
| 	// if t is an interface | ||||
| 	if t.Kind() == reflect.Interface { | ||||
| 		for k, v := range i.values { | ||||
| 			if k.Implements(t) { | ||||
| 				val = v | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Still no type found, try to look it up on the parent | ||||
| 	if !val.IsValid() && i.parent != nil { | ||||
| 		val = i.parent.GetVal(t) | ||||
| 	} | ||||
|  | ||||
| 	return val | ||||
|  | ||||
| } | ||||
|  | ||||
| func (i *injector) SetParent(parent Injector) { | ||||
| 	i.parent = parent | ||||
| } | ||||
							
								
								
									
										191
									
								
								vendor/github.com/go-macaron/session/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/session/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										20
									
								
								vendor/github.com/go-macaron/session/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/go-macaron/session/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # session [](https://travis-ci.org/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
									
								
							
							
						
						
									
										261
									
								
								vendor/github.com/go-macaron/session/file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										217
									
								
								vendor/github.com/go-macaron/session/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | ||||
| // Copyright 2013 Beego Authors | ||||
| // Copyright 2014 The Macaron Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||||
| // not use this file except in compliance with the License. You may obtain | ||||
| // a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| // License for the specific language governing permissions and limitations | ||||
| // under the License. | ||||
|  | ||||
| package session | ||||
|  | ||||
| import ( | ||||
| 	"container/list" | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // MemStore represents a in-memory session store implementation. | ||||
| type MemStore struct { | ||||
| 	sid        string | ||||
| 	lock       sync.RWMutex | ||||
| 	data       map[interface{}]interface{} | ||||
| 	lastAccess time.Time | ||||
| } | ||||
|  | ||||
| // NewMemStore creates and returns a memory session store. | ||||
| func NewMemStore(sid string) *MemStore { | ||||
| 	return &MemStore{ | ||||
| 		sid:        sid, | ||||
| 		data:       make(map[interface{}]interface{}), | ||||
| 		lastAccess: time.Now(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Set sets value to given key in session. | ||||
| func (s *MemStore) Set(key, val interface{}) error { | ||||
| 	s.lock.Lock() | ||||
| 	defer s.lock.Unlock() | ||||
|  | ||||
| 	s.data[key] = val | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Get gets value by given key in session. | ||||
| func (s *MemStore) Get(key interface{}) interface{} { | ||||
| 	s.lock.RLock() | ||||
| 	defer s.lock.RUnlock() | ||||
|  | ||||
| 	return s.data[key] | ||||
| } | ||||
|  | ||||
| // Delete deletes a key from session. | ||||
| func (s *MemStore) Delete(key interface{}) error { | ||||
| 	s.lock.Lock() | ||||
| 	defer s.lock.Unlock() | ||||
|  | ||||
| 	delete(s.data, key) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ID returns current session ID. | ||||
| func (s *MemStore) ID() string { | ||||
| 	return s.sid | ||||
| } | ||||
|  | ||||
| // Release releases resource and save data to provider. | ||||
| func (_ *MemStore) Release() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Flush deletes all session data. | ||||
| func (s *MemStore) Flush() error { | ||||
| 	s.lock.Lock() | ||||
| 	defer s.lock.Unlock() | ||||
|  | ||||
| 	s.data = make(map[interface{}]interface{}) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // MemProvider represents a in-memory session provider implementation. | ||||
| type MemProvider struct { | ||||
| 	lock        sync.RWMutex | ||||
| 	maxLifetime int64 | ||||
| 	data        map[string]*list.Element | ||||
| 	// A priority list whose lastAccess newer gets higer priority. | ||||
| 	list *list.List | ||||
| } | ||||
|  | ||||
| // Init initializes memory session provider. | ||||
| func (p *MemProvider) Init(maxLifetime int64, _ string) error { | ||||
| 	p.lock.Lock() | ||||
| 	p.maxLifetime = maxLifetime | ||||
| 	p.lock.Unlock() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // update expands time of session store by given ID. | ||||
| func (p *MemProvider) update(sid string) error { | ||||
| 	p.lock.Lock() | ||||
| 	defer p.lock.Unlock() | ||||
|  | ||||
| 	if e, ok := p.data[sid]; ok { | ||||
| 		e.Value.(*MemStore).lastAccess = time.Now() | ||||
| 		p.list.MoveToFront(e) | ||||
| 		return nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Read returns raw session store by session ID. | ||||
| func (p *MemProvider) Read(sid string) (_ RawStore, err error) { | ||||
| 	p.lock.RLock() | ||||
| 	e, ok := p.data[sid] | ||||
| 	p.lock.RUnlock() | ||||
|  | ||||
| 	if ok { | ||||
| 		if err = p.update(sid); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return e.Value.(*MemStore), nil | ||||
| 	} | ||||
|  | ||||
| 	// Create a new session. | ||||
| 	p.lock.Lock() | ||||
| 	defer p.lock.Unlock() | ||||
|  | ||||
| 	s := NewMemStore(sid) | ||||
| 	p.data[sid] = p.list.PushBack(s) | ||||
| 	return s, nil | ||||
| } | ||||
|  | ||||
| // Exist returns true if session with given ID exists. | ||||
| func (p *MemProvider) Exist(sid string) bool { | ||||
| 	p.lock.RLock() | ||||
| 	defer p.lock.RUnlock() | ||||
|  | ||||
| 	_, ok := p.data[sid] | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // 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
									
								
							
							
						
						
									
										235
									
								
								vendor/github.com/go-macaron/session/redis/redis.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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{}) | ||||
| } | ||||
							
								
								
									
										1
									
								
								vendor/github.com/go-macaron/session/redis/redis.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/go-macaron/session/redis/redis.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ignore | ||||
							
								
								
									
										399
									
								
								vendor/github.com/go-macaron/session/session.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								vendor/github.com/go-macaron/session/session.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/go-macaron/session/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/toolbox/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| Apache License | ||||
| Version 2.0, January 2004 | ||||
| http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
| "License" shall mean the terms and conditions for use, reproduction, and | ||||
| distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | ||||
| owner that is granting the License. | ||||
|  | ||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | ||||
| that control, are controlled by, or are under common control with that entity. | ||||
| For the purposes of this definition, "control" means (i) the power, direct or | ||||
| indirect, to cause the direction or management of such entity, whether by | ||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising | ||||
| permissions granted by this License. | ||||
|  | ||||
| "Source" form shall mean the preferred form for making modifications, including | ||||
| but not limited to software source code, documentation source, and configuration | ||||
| files. | ||||
|  | ||||
| "Object" form shall mean any form resulting from mechanical transformation or | ||||
| translation of a Source form, including but not limited to compiled object code, | ||||
| generated documentation, and conversions to other media types. | ||||
|  | ||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made | ||||
| available under the License, as indicated by a copyright notice that is included | ||||
| in or attached to the work (an example is provided in the Appendix below). | ||||
|  | ||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that | ||||
| is based on (or derived from) the Work and for which the editorial revisions, | ||||
| annotations, elaborations, or other modifications represent, as a whole, an | ||||
| original work of authorship. For the purposes of this License, Derivative Works | ||||
| shall not include works that remain separable from, or merely link (or bind by | ||||
| name) to the interfaces of, the Work and Derivative Works thereof. | ||||
|  | ||||
| "Contribution" shall mean any work of authorship, including the original version | ||||
| of the Work and any modifications or additions to that Work or Derivative Works | ||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work | ||||
| by the copyright owner or by an individual or Legal Entity authorized to submit | ||||
| on behalf of the copyright owner. For the purposes of this definition, | ||||
| "submitted" means any form of electronic, verbal, or written communication sent | ||||
| to the Licensor or its representatives, including but not limited to | ||||
| communication on electronic mailing lists, source code control systems, and | ||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for | ||||
| the purpose of discussing and improving the Work, but excluding communication | ||||
| that is conspicuously marked or otherwise designated in writing by the copyright | ||||
| owner as "Not a Contribution." | ||||
|  | ||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf | ||||
| of whom a Contribution has been received by Licensor and subsequently | ||||
| incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, | ||||
| publicly display, publicly perform, sublicense, and distribute the Work and such | ||||
| Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. | ||||
|  | ||||
| Subject to the terms and conditions of this License, each Contributor hereby | ||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | ||||
| irrevocable (except as stated in this section) patent license to make, have | ||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where | ||||
| such license applies only to those patent claims licensable by such Contributor | ||||
| that are necessarily infringed by their Contribution(s) alone or by combination | ||||
| of their Contribution(s) with the Work to which such Contribution(s) was | ||||
| submitted. If You institute patent litigation against any entity (including a | ||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a | ||||
| Contribution incorporated within the Work constitutes direct or contributory | ||||
| patent infringement, then any patent licenses granted to You under this License | ||||
| for that Work shall terminate as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. | ||||
|  | ||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof | ||||
| in any medium, with or without modifications, and in Source or Object form, | ||||
| provided that You meet the following conditions: | ||||
|  | ||||
| You must give any other recipients of the Work or Derivative Works a copy of | ||||
| this License; and | ||||
| You must cause any modified files to carry prominent notices stating that You | ||||
| changed the files; and | ||||
| You must retain, in the Source form of any Derivative Works that You distribute, | ||||
| all copyright, patent, trademark, and attribution notices from the Source form | ||||
| of the Work, excluding those notices that do not pertain to any part of the | ||||
| Derivative Works; and | ||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any | ||||
| Derivative Works that You distribute must include a readable copy of the | ||||
| attribution notices contained within such NOTICE file, excluding those notices | ||||
| that do not pertain to any part of the Derivative Works, in at least one of the | ||||
| following places: within a NOTICE text file distributed as part of the | ||||
| Derivative Works; within the Source form or documentation, if provided along | ||||
| with the Derivative Works; or, within a display generated by the Derivative | ||||
| Works, if and wherever such third-party notices normally appear. The contents of | ||||
| the NOTICE file are for informational purposes only and do not modify the | ||||
| License. You may add Your own attribution notices within Derivative Works that | ||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||||
| provided that such additional attribution notices cannot be construed as | ||||
| modifying the License. | ||||
| You may add Your own copyright statement to Your modifications and may provide | ||||
| additional or different license terms and conditions for use, reproduction, or | ||||
| distribution of Your modifications, or for any such Derivative Works as a whole, | ||||
| provided Your use, reproduction, and distribution of the Work otherwise complies | ||||
| with the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. | ||||
|  | ||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted | ||||
| for inclusion in the Work by You to the Licensor shall be under the terms and | ||||
| conditions of this License, without any additional terms or conditions. | ||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of | ||||
| any separate license agreement you may have executed with Licensor regarding | ||||
| such Contributions. | ||||
|  | ||||
| 6. Trademarks. | ||||
|  | ||||
| This License does not grant permission to use the trade names, trademarks, | ||||
| service marks, or product names of the Licensor, except as required for | ||||
| reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, Licensor provides the | ||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | ||||
| including, without limitation, any warranties or conditions of TITLE, | ||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | ||||
| solely responsible for determining the appropriateness of using or | ||||
| redistributing the Work and assume any risks associated with Your exercise of | ||||
| permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. | ||||
|  | ||||
| In no event and under no legal theory, whether in tort (including negligence), | ||||
| contract, or otherwise, unless required by applicable law (such as deliberate | ||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be | ||||
| liable to You for damages, including any direct, indirect, special, incidental, | ||||
| or consequential damages of any character arising as a result of this License or | ||||
| out of the use or inability to use the Work (including but not limited to | ||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or | ||||
| any and all other commercial damages or losses), even if such Contributor has | ||||
| been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. | ||||
|  | ||||
| While redistributing the Work or Derivative Works thereof, You may choose to | ||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or | ||||
| other liability obligations and/or rights consistent with this License. However, | ||||
| in accepting such obligations, You may act only on Your own behalf and on Your | ||||
| sole responsibility, not on behalf of any other Contributor, and only if You | ||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability | ||||
| incurred by, or claims asserted against, such Contributor by reason of your | ||||
| accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work | ||||
|  | ||||
| To apply the Apache License to your work, attach the following boilerplate | ||||
| notice, with the fields enclosed by brackets "[]" replaced with your own | ||||
| identifying information. (Don't include the brackets!) The text should be | ||||
| enclosed in the appropriate comment syntax for the file format. We also | ||||
| recommend that a file or class name and description of purpose be included on | ||||
| the same "printed page" as the copyright notice for easier identification within | ||||
| third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										110
									
								
								vendor/github.com/go-macaron/toolbox/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/go-macaron/toolbox/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										83
									
								
								vendor/github.com/go-macaron/toolbox/healthcheck.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										163
									
								
								vendor/github.com/go-macaron/toolbox/profile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/go-macaron/toolbox/statistic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										154
									
								
								vendor/github.com/go-macaron/toolbox/toolbox.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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)) | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user