所有依赖包移入vendor中

pull/21/merge
ouqiang 2017-03-01 14:59:46 +08:00
parent a30967b550
commit b39e6596b0
246 changed files with 61586 additions and 0 deletions

191
vendor/github.com/Unknwon/com/LICENSE generated vendored Normal file
View File

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

20
vendor/github.com/Unknwon/com/README.md generated vendored Normal file
View File

@ -0,0 +1,20 @@
Common Functions
================
[![Build Status](https://travis-ci.org/Unknwon/com.svg)](https://travis-ci.org/Unknwon/com) [![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/Unknwon/com)
This is an open source project for commonly used functions for the Go programming language.
This package need >= **go 1.2**
Code Convention: based on [Go Code Convention](https://github.com/Unknwon/go-code-convention).
## Contribute
Your contribute is welcome, but you have to check following steps after you added some functions and commit them:
1. Make sure you wrote user-friendly comments for **all functions** .
2. Make sure you wrote test cases with any possible condition for **all functions** in file `*_test.go`.
3. Make sure you wrote benchmarks for **all functions** in file `*_test.go`.
4. Make sure you wrote useful examples for **all functions** in file `example_test.go`.
5. Make sure you ran `go test` and got **PASS** .

161
vendor/github.com/Unknwon/com/cmd.go generated vendored Normal file
View File

@ -0,0 +1,161 @@
// +build go1.2
// Copyright 2013 com 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 com is an open source project for commonly used functions for the Go programming language.
package com
import (
"bytes"
"fmt"
"os/exec"
"runtime"
"strings"
)
// ExecCmdDirBytes executes system command in given directory
// and return stdout, stderr in bytes type, along with possible error.
func ExecCmdDirBytes(dir, cmdName string, args ...string) ([]byte, []byte, error) {
bufOut := new(bytes.Buffer)
bufErr := new(bytes.Buffer)
cmd := exec.Command(cmdName, args...)
cmd.Dir = dir
cmd.Stdout = bufOut
cmd.Stderr = bufErr
err := cmd.Run()
return bufOut.Bytes(), bufErr.Bytes(), err
}
// ExecCmdBytes executes system command
// and return stdout, stderr in bytes type, along with possible error.
func ExecCmdBytes(cmdName string, args ...string) ([]byte, []byte, error) {
return ExecCmdDirBytes("", cmdName, args...)
}
// ExecCmdDir executes system command in given directory
// and return stdout, stderr in string type, along with possible error.
func ExecCmdDir(dir, cmdName string, args ...string) (string, string, error) {
bufOut, bufErr, err := ExecCmdDirBytes(dir, cmdName, args...)
return string(bufOut), string(bufErr), err
}
// ExecCmd executes system command
// and return stdout, stderr in string type, along with possible error.
func ExecCmd(cmdName string, args ...string) (string, string, error) {
return ExecCmdDir("", cmdName, args...)
}
// _________ .__ .____
// \_ ___ \ ____ | | ___________ | | ____ ____
// / \ \/ / _ \| | / _ \_ __ \ | | / _ \ / ___\
// \ \___( <_> ) |_( <_> ) | \/ | |__( <_> ) /_/ >
// \______ /\____/|____/\____/|__| |_______ \____/\___ /
// \/ \/ /_____/
// Color number constants.
const (
Gray = uint8(iota + 90)
Red
Green
Yellow
Blue
Magenta
//NRed = uint8(31) // Normal
EndColor = "\033[0m"
)
// getColorLevel returns colored level string by given level.
func getColorLevel(level string) string {
level = strings.ToUpper(level)
switch level {
case "TRAC":
return fmt.Sprintf("\033[%dm%s\033[0m", Blue, level)
case "ERRO":
return fmt.Sprintf("\033[%dm%s\033[0m", Red, level)
case "WARN":
return fmt.Sprintf("\033[%dm%s\033[0m", Magenta, level)
case "SUCC":
return fmt.Sprintf("\033[%dm%s\033[0m", Green, level)
default:
return level
}
}
// ColorLogS colors log and return colored content.
// Log format: <level> <content [highlight][path]> [ error ].
// Level: TRAC -> blue; ERRO -> red; WARN -> Magenta; SUCC -> green; others -> default.
// Content: default; path: yellow; error -> red.
// Level has to be surrounded by "[" and "]".
// Highlights have to be surrounded by "# " and " #"(space), "#" will be deleted.
// Paths have to be surrounded by "( " and " )"(space).
// Errors have to be surrounded by "[ " and " ]"(space).
// Note: it hasn't support windows yet, contribute is welcome.
func ColorLogS(format string, a ...interface{}) string {
log := fmt.Sprintf(format, a...)
var clog string
if runtime.GOOS != "windows" {
// Level.
i := strings.Index(log, "]")
if log[0] == '[' && i > -1 {
clog += "[" + getColorLevel(log[1:i]) + "]"
}
log = log[i+1:]
// Error.
log = strings.Replace(log, "[ ", fmt.Sprintf("[\033[%dm", Red), -1)
log = strings.Replace(log, " ]", EndColor+"]", -1)
// Path.
log = strings.Replace(log, "( ", fmt.Sprintf("(\033[%dm", Yellow), -1)
log = strings.Replace(log, " )", EndColor+")", -1)
// Highlights.
log = strings.Replace(log, "# ", fmt.Sprintf("\033[%dm", Gray), -1)
log = strings.Replace(log, " #", EndColor, -1)
} else {
// Level.
i := strings.Index(log, "]")
if log[0] == '[' && i > -1 {
clog += "[" + log[1:i] + "]"
}
log = log[i+1:]
// Error.
log = strings.Replace(log, "[ ", "[", -1)
log = strings.Replace(log, " ]", "]", -1)
// Path.
log = strings.Replace(log, "( ", "(", -1)
log = strings.Replace(log, " )", ")", -1)
// Highlights.
log = strings.Replace(log, "# ", "", -1)
log = strings.Replace(log, " #", "", -1)
}
return clog + log
}
// ColorLog prints colored log to stdout.
// See color rules in function 'ColorLogS'.
func ColorLog(format string, a ...interface{}) {
fmt.Print(ColorLogS(format, a...))
}

157
vendor/github.com/Unknwon/com/convert.go generated vendored Normal file
View File

@ -0,0 +1,157 @@
// Copyright 2014 com 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 com
import (
"fmt"
"strconv"
)
// Convert string to specify type.
type StrTo string
func (f StrTo) Exist() bool {
return string(f) != string(0x1E)
}
func (f StrTo) Uint8() (uint8, error) {
v, err := strconv.ParseUint(f.String(), 10, 8)
return uint8(v), err
}
func (f StrTo) Int() (int, error) {
v, err := strconv.ParseInt(f.String(), 10, 0)
return int(v), err
}
func (f StrTo) Int64() (int64, error) {
v, err := strconv.ParseInt(f.String(), 10, 64)
return int64(v), err
}
func (f StrTo) MustUint8() uint8 {
v, _ := f.Uint8()
return v
}
func (f StrTo) MustInt() int {
v, _ := f.Int()
return v
}
func (f StrTo) MustInt64() int64 {
v, _ := f.Int64()
return v
}
func (f StrTo) String() string {
if f.Exist() {
return string(f)
}
return ""
}
// Convert any type to string.
func ToStr(value interface{}, args ...int) (s string) {
switch v := value.(type) {
case bool:
s = strconv.FormatBool(v)
case float32:
s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
case float64:
s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
case int:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int8:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int16:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int32:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int64:
s = strconv.FormatInt(v, argInt(args).Get(0, 10))
case uint:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint8:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint16:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint32:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint64:
s = strconv.FormatUint(v, argInt(args).Get(0, 10))
case string:
s = v
case []byte:
s = string(v)
default:
s = fmt.Sprintf("%v", v)
}
return s
}
type argInt []int
func (a argInt) Get(i int, args ...int) (r int) {
if i >= 0 && i < len(a) {
r = a[i]
} else if len(args) > 0 {
r = args[0]
}
return
}
// HexStr2int converts hex format string to decimal number.
func HexStr2int(hexStr string) (int, error) {
num := 0
length := len(hexStr)
for i := 0; i < length; i++ {
char := hexStr[length-i-1]
factor := -1
switch {
case char >= '0' && char <= '9':
factor = int(char) - '0'
case char >= 'a' && char <= 'f':
factor = int(char) - 'a' + 10
default:
return -1, fmt.Errorf("invalid hex: %s", string(char))
}
num += factor * PowInt(16, i)
}
return num, nil
}
// Int2HexStr converts decimal number to hex format string.
func Int2HexStr(num int) (hex string) {
if num == 0 {
return "0"
}
for num > 0 {
r := num % 16
c := "?"
if r >= 0 && r <= 9 {
c = string(r + '0')
} else {
c = string(r + 'a' - 10)
}
hex = c + hex
num = num / 16
}
return hex
}

173
vendor/github.com/Unknwon/com/dir.go generated vendored Normal file
View File

@ -0,0 +1,173 @@
// Copyright 2013 com 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 com
import (
"errors"
"fmt"
"os"
"path"
"strings"
)
// IsDir returns true if given path is a directory,
// or returns false when it's a file or does not exist.
func IsDir(dir string) bool {
f, e := os.Stat(dir)
if e != nil {
return false
}
return f.IsDir()
}
func statDir(dirPath, recPath string, includeDir, isDirOnly bool) ([]string, error) {
dir, err := os.Open(dirPath)
if err != nil {
return nil, err
}
defer dir.Close()
fis, err := dir.Readdir(0)
if err != nil {
return nil, err
}
statList := make([]string, 0)
for _, fi := range fis {
if strings.Contains(fi.Name(), ".DS_Store") {
continue
}
relPath := path.Join(recPath, fi.Name())
curPath := path.Join(dirPath, fi.Name())
if fi.IsDir() {
if includeDir {
statList = append(statList, relPath+"/")
}
s, err := statDir(curPath, relPath, includeDir, isDirOnly)
if err != nil {
return nil, err
}
statList = append(statList, s...)
} else if !isDirOnly {
statList = append(statList, relPath)
}
}
return statList, nil
}
// StatDir gathers information of given directory by depth-first.
// It returns slice of file list and includes subdirectories if enabled;
// it returns error and nil slice when error occurs in underlying functions,
// or given path is not a directory or does not exist.
//
// Slice does not include given path itself.
// If subdirectories is enabled, they will have suffix '/'.
func StatDir(rootPath string, includeDir ...bool) ([]string, error) {
if !IsDir(rootPath) {
return nil, errors.New("not a directory or does not exist: " + rootPath)
}
isIncludeDir := false
if len(includeDir) >= 1 {
isIncludeDir = includeDir[0]
}
return statDir(rootPath, "", isIncludeDir, false)
}
// GetAllSubDirs returns all subdirectories of given root path.
// Slice does not include given path itself.
func GetAllSubDirs(rootPath string) ([]string, error) {
if !IsDir(rootPath) {
return nil, errors.New("not a directory or does not exist: " + rootPath)
}
return statDir(rootPath, "", true, true)
}
// GetFileListBySuffix returns an ordered list of file paths.
// It recognize if given path is a file, and don't do recursive find.
func GetFileListBySuffix(dirPath, suffix string) ([]string, error) {
if !IsExist(dirPath) {
return nil, fmt.Errorf("given path does not exist: %s", dirPath)
} else if IsFile(dirPath) {
return []string{dirPath}, nil
}
// Given path is a directory.
dir, err := os.Open(dirPath)
if err != nil {
return nil, err
}
fis, err := dir.Readdir(0)
if err != nil {
return nil, err
}
files := make([]string, 0, len(fis))
for _, fi := range fis {
if strings.HasSuffix(fi.Name(), suffix) {
files = append(files, path.Join(dirPath, fi.Name()))
}
}
return files, nil
}
// CopyDir copy files recursively from source to target directory.
//
// The filter accepts a function that process the path info.
// and should return true for need to filter.
//
// It returns error when error occurs in underlying functions.
func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error {
// Check if target directory exists.
if IsExist(destPath) {
return errors.New("file or directory alreay exists: " + destPath)
}
err := os.MkdirAll(destPath, os.ModePerm)
if err != nil {
return err
}
// Gather directory info.
infos, err := StatDir(srcPath, true)
if err != nil {
return err
}
var filter func(filePath string) bool
if len(filters) > 0 {
filter = filters[0]
}
for _, info := range infos {
if filter != nil && filter(info) {
continue
}
curPath := path.Join(destPath, info)
if strings.HasSuffix(info, "/") {
err = os.MkdirAll(curPath, os.ModePerm)
} else {
err = Copy(path.Join(srcPath, info), curPath)
}
if err != nil {
return err
}
}
return nil
}

145
vendor/github.com/Unknwon/com/file.go generated vendored Normal file
View File

@ -0,0 +1,145 @@
// Copyright 2013 com 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 com
import (
"fmt"
"io"
"io/ioutil"
"math"
"os"
"path"
)
// Storage unit constants.
const (
Byte = 1
KByte = Byte * 1024
MByte = KByte * 1024
GByte = MByte * 1024
TByte = GByte * 1024
PByte = TByte * 1024
EByte = PByte * 1024
)
func logn(n, b float64) float64 {
return math.Log(n) / math.Log(b)
}
func humanateBytes(s uint64, base float64, sizes []string) string {
if s < 10 {
return fmt.Sprintf("%dB", s)
}
e := math.Floor(logn(float64(s), base))
suffix := sizes[int(e)]
val := float64(s) / math.Pow(base, math.Floor(e))
f := "%.0f"
if val < 10 {
f = "%.1f"
}
return fmt.Sprintf(f+"%s", val, suffix)
}
// HumaneFileSize calculates the file size and generate user-friendly string.
func HumaneFileSize(s uint64) string {
sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
return humanateBytes(s, 1024, sizes)
}
// FileMTime returns file modified time and possible error.
func FileMTime(file string) (int64, error) {
f, err := os.Stat(file)
if err != nil {
return 0, err
}
return f.ModTime().Unix(), nil
}
// FileSize returns file size in bytes and possible error.
func FileSize(file string) (int64, error) {
f, err := os.Stat(file)
if err != nil {
return 0, err
}
return f.Size(), nil
}
// Copy copies file from source to target path.
func Copy(src, dest string) error {
// Gather file information to set back later.
si, err := os.Lstat(src)
if err != nil {
return err
}
// Handle symbolic link.
if si.Mode()&os.ModeSymlink != 0 {
target, err := os.Readlink(src)
if err != nil {
return err
}
// NOTE: os.Chmod and os.Chtimes don't recoganize symbolic link,
// which will lead "no such file or directory" error.
return os.Symlink(target, dest)
}
sr, err := os.Open(src)
if err != nil {
return err
}
defer sr.Close()
dw, err := os.Create(dest)
if err != nil {
return err
}
defer dw.Close()
if _, err = io.Copy(dw, sr); err != nil {
return err
}
// Set back file information.
if err = os.Chtimes(dest, si.ModTime(), si.ModTime()); err != nil {
return err
}
return os.Chmod(dest, si.Mode())
}
// WriteFile writes data to a file named by filename.
// If the file does not exist, WriteFile creates it
// and its upper level paths.
func WriteFile(filename string, data []byte) error {
os.MkdirAll(path.Dir(filename), os.ModePerm)
return ioutil.WriteFile(filename, data, 0655)
}
// IsFile returns true if given path is a file,
// or returns false when it's a directory or does not exist.
func IsFile(filePath string) bool {
f, e := os.Stat(filePath)
if e != nil {
return false
}
return !f.IsDir()
}
// IsExist checks whether a file or directory exists.
// It returns false when the file or directory does not exist.
func IsExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}

60
vendor/github.com/Unknwon/com/html.go generated vendored Normal file
View File

@ -0,0 +1,60 @@
// Copyright 2013 com 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 com
import (
"html"
"regexp"
"strings"
)
// Html2JS converts []byte type of HTML content into JS format.
func Html2JS(data []byte) []byte {
s := string(data)
s = strings.Replace(s, `\`, `\\`, -1)
s = strings.Replace(s, "\n", `\n`, -1)
s = strings.Replace(s, "\r", "", -1)
s = strings.Replace(s, "\"", `\"`, -1)
s = strings.Replace(s, "<table>", "&lt;table>", -1)
return []byte(s)
}
// encode html chars to string
func HtmlEncode(str string) string {
return html.EscapeString(str)
}
// decode string to html chars
func HtmlDecode(str string) string {
return html.UnescapeString(str)
}
// strip tags in html string
func StripTags(src string) string {
//去除style,script,html tag
re := regexp.MustCompile(`(?s)<(?:style|script)[^<>]*>.*?</(?:style|script)>|</?[a-z][a-z0-9]*[^<>]*>|<!--.*?-->`)
src = re.ReplaceAllString(src, "")
//trim all spaces(2+) into \n
re = regexp.MustCompile(`\s{2,}`)
src = re.ReplaceAllString(src, "\n")
return strings.TrimSpace(src)
}
// change \n to <br/>
func Nl2br(str string) string {
return strings.Replace(str, "\n", "<br/>", -1)
}

201
vendor/github.com/Unknwon/com/http.go generated vendored Normal file
View File

@ -0,0 +1,201 @@
// Copyright 2013 com 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 com
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path"
)
type NotFoundError struct {
Message string
}
func (e NotFoundError) Error() string {
return e.Message
}
type RemoteError struct {
Host string
Err error
}
func (e *RemoteError) Error() string {
return e.Err.Error()
}
var UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1541.0 Safari/537.36"
// HttpCall makes HTTP method call.
func HttpCall(client *http.Client, method, url string, header http.Header, body io.Reader) (io.ReadCloser, error) {
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
req.Header.Set("User-Agent", UserAgent)
for k, vs := range header {
req.Header[k] = vs
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode == 200 {
return resp.Body, nil
}
resp.Body.Close()
if resp.StatusCode == 404 { // 403 can be rate limit error. || resp.StatusCode == 403 {
err = fmt.Errorf("resource not found: %s", url)
} else {
err = fmt.Errorf("%s %s -> %d", method, url, resp.StatusCode)
}
return nil, err
}
// HttpGet gets the specified resource.
// ErrNotFound is returned if the server responds with status 404.
func HttpGet(client *http.Client, url string, header http.Header) (io.ReadCloser, error) {
return HttpCall(client, "GET", url, header, nil)
}
// HttpPost posts the specified resource.
// ErrNotFound is returned if the server responds with status 404.
func HttpPost(client *http.Client, url string, header http.Header, body []byte) (io.ReadCloser, error) {
return HttpCall(client, "POST", url, header, bytes.NewBuffer(body))
}
// HttpGetToFile gets the specified resource and writes to file.
// ErrNotFound is returned if the server responds with status 404.
func HttpGetToFile(client *http.Client, url string, header http.Header, fileName string) error {
rc, err := HttpGet(client, url, header)
if err != nil {
return err
}
defer rc.Close()
os.MkdirAll(path.Dir(fileName), os.ModePerm)
f, err := os.Create(fileName)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, rc)
return err
}
// HttpGetBytes gets the specified resource. ErrNotFound is returned if the server
// responds with status 404.
func HttpGetBytes(client *http.Client, url string, header http.Header) ([]byte, error) {
rc, err := HttpGet(client, url, header)
if err != nil {
return nil, err
}
defer rc.Close()
return ioutil.ReadAll(rc)
}
// HttpGetJSON gets the specified resource and mapping to struct.
// ErrNotFound is returned if the server responds with status 404.
func HttpGetJSON(client *http.Client, url string, v interface{}) error {
rc, err := HttpGet(client, url, nil)
if err != nil {
return err
}
defer rc.Close()
err = json.NewDecoder(rc).Decode(v)
if _, ok := err.(*json.SyntaxError); ok {
return fmt.Errorf("JSON syntax error at %s", url)
}
return nil
}
// HttpPostJSON posts the specified resource with struct values,
// and maps results to struct.
// ErrNotFound is returned if the server responds with status 404.
func HttpPostJSON(client *http.Client, url string, body, v interface{}) error {
data, err := json.Marshal(body)
if err != nil {
return err
}
rc, err := HttpPost(client, url, http.Header{"content-type": []string{"application/json"}}, data)
if err != nil {
return err
}
defer rc.Close()
err = json.NewDecoder(rc).Decode(v)
if _, ok := err.(*json.SyntaxError); ok {
return fmt.Errorf("JSON syntax error at %s", url)
}
return nil
}
// A RawFile describes a file that can be downloaded.
type RawFile interface {
Name() string
RawUrl() string
Data() []byte
SetData([]byte)
}
// FetchFiles fetches files specified by the rawURL field in parallel.
func FetchFiles(client *http.Client, files []RawFile, header http.Header) error {
ch := make(chan error, len(files))
for i := range files {
go func(i int) {
p, err := HttpGetBytes(client, files[i].RawUrl(), nil)
if err != nil {
ch <- err
return
}
files[i].SetData(p)
ch <- nil
}(i)
}
for _ = range files {
if err := <-ch; err != nil {
return err
}
}
return nil
}
// FetchFiles uses command `curl` to fetch files specified by the rawURL field in parallel.
func FetchFilesCurl(files []RawFile, curlOptions ...string) error {
ch := make(chan error, len(files))
for i := range files {
go func(i int) {
stdout, _, err := ExecCmd("curl", append(curlOptions, files[i].RawUrl())...)
if err != nil {
ch <- err
return
}
files[i].SetData([]byte(stdout))
ch <- nil
}(i)
}
for _ = range files {
if err := <-ch; err != nil {
return err
}
}
return nil
}

29
vendor/github.com/Unknwon/com/math.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2014 com 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 com
// PowInt is int type of math.Pow function.
func PowInt(x int, y int) int {
if y <= 0 {
return 1
} else {
if y % 2 == 0 {
sqrt := PowInt(x, y/2)
return sqrt * sqrt
} else {
return PowInt(x, y-1) * x
}
}
}

80
vendor/github.com/Unknwon/com/path.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2013 com 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 com
import (
"errors"
"os"
"path/filepath"
"runtime"
"strings"
)
// GetGOPATHs returns all paths in GOPATH variable.
func GetGOPATHs() []string {
gopath := os.Getenv("GOPATH")
var paths []string
if runtime.GOOS == "windows" {
gopath = strings.Replace(gopath, "\\", "/", -1)
paths = strings.Split(gopath, ";")
} else {
paths = strings.Split(gopath, ":")
}
return paths
}
// GetSrcPath returns app. source code path.
// It only works when you have src. folder in GOPATH,
// it returns error not able to locate source folder path.
func GetSrcPath(importPath string) (appPath string, err error) {
paths := GetGOPATHs()
for _, p := range paths {
if IsExist(p + "/src/" + importPath + "/") {
appPath = p + "/src/" + importPath + "/"
break
}
}
if len(appPath) == 0 {
return "", errors.New("Unable to locate source folder path")
}
appPath = filepath.Dir(appPath) + "/"
if runtime.GOOS == "windows" {
// Replace all '\' to '/'.
appPath = strings.Replace(appPath, "\\", "/", -1)
}
return appPath, nil
}
// HomeDir returns path of '~'(in Linux) on Windows,
// it returns error when the variable does not exist.
func HomeDir() (home string, err error) {
if runtime.GOOS == "windows" {
home = os.Getenv("USERPROFILE")
if len(home) == 0 {
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
}
} else {
home = os.Getenv("HOME")
}
if len(home) == 0 {
return "", errors.New("Cannot specify home directory because it's empty")
}
return home, nil
}

56
vendor/github.com/Unknwon/com/regex.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
// Copyright 2013 com 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 com
import "regexp"
const (
regex_email_pattern = `(?i)[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}`
regex_strict_email_pattern = `(?i)[A-Z0-9!#$%&'*+/=?^_{|}~-]+` +
`(?:\.[A-Z0-9!#$%&'*+/=?^_{|}~-]+)*` +
`@(?:[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?\.)+` +
`[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?`
regex_url_pattern = `(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?`
)
var (
regex_email *regexp.Regexp
regex_strict_email *regexp.Regexp
regex_url *regexp.Regexp
)
func init() {
regex_email = regexp.MustCompile(regex_email_pattern)
regex_strict_email = regexp.MustCompile(regex_strict_email_pattern)
regex_url = regexp.MustCompile(regex_url_pattern)
}
// validate string is an email address, if not return false
// basically validation can match 99% cases
func IsEmail(email string) bool {
return regex_email.MatchString(email)
}
// validate string is an email address, if not return false
// this validation omits RFC 2822
func IsEmailRFC(email string) bool {
return regex_strict_email.MatchString(email)
}
// validate string is a url link, if not return false
// simple validation can match 99% cases
func IsUrl(url string) bool {
return regex_url.MatchString(url)
}

87
vendor/github.com/Unknwon/com/slice.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
// Copyright 2013 com 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 com
import (
"strings"
)
// AppendStr appends string to slice with no duplicates.
func AppendStr(strs []string, str string) []string {
for _, s := range strs {
if s == str {
return strs
}
}
return append(strs, str)
}
// CompareSliceStr compares two 'string' type slices.
// It returns true if elements and order are both the same.
func CompareSliceStr(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
for i := range s1 {
if s1[i] != s2[i] {
return false
}
}
return true
}
// CompareSliceStr compares two 'string' type slices.
// It returns true if elements are the same, and ignores the order.
func CompareSliceStrU(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
for i := range s1 {
for j := len(s2) - 1; j >= 0; j-- {
if s1[i] == s2[j] {
s2 = append(s2[:j], s2[j+1:]...)
break
}
}
}
if len(s2) > 0 {
return false
}
return true
}
// IsSliceContainsStr returns true if the string exists in given slice, ignore case.
func IsSliceContainsStr(sl []string, str string) bool {
str = strings.ToLower(str)
for _, s := range sl {
if strings.ToLower(s) == str {
return true
}
}
return false
}
// IsSliceContainsInt64 returns true if the int64 exists in given slice.
func IsSliceContainsInt64(sl []int64, i int64) bool {
for _, s := range sl {
if s == i {
return true
}
}
return false
}

253
vendor/github.com/Unknwon/com/string.go generated vendored Normal file
View File

@ -0,0 +1,253 @@
// Copyright 2013 com 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 com
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
r "math/rand"
"strconv"
"strings"
"time"
"unicode"
"unicode/utf8"
)
// AESGCMEncrypt encrypts plaintext with the given key using AES in GCM mode.
func AESGCMEncrypt(key, plaintext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nil, nonce, plaintext, nil)
return append(nonce, ciphertext...), nil
}
// AESGCMDecrypt decrypts ciphertext with the given key using AES in GCM mode.
func AESGCMDecrypt(key, ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
size := gcm.NonceSize()
if len(ciphertext)-size <= 0 {
return nil, errors.New("Ciphertext is empty")
}
nonce := ciphertext[:size]
ciphertext = ciphertext[size:]
plainText, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plainText, nil
}
// IsLetter returns true if the 'l' is an English letter.
func IsLetter(l uint8) bool {
n := (l | 0x20) - 'a'
if n >= 0 && n < 26 {
return true
}
return false
}
// Expand replaces {k} in template with match[k] or subs[atoi(k)] if k is not in match.
func Expand(template string, match map[string]string, subs ...string) string {
var p []byte
var i int
for {
i = strings.Index(template, "{")
if i < 0 {
break
}
p = append(p, template[:i]...)
template = template[i+1:]
i = strings.Index(template, "}")
if s, ok := match[template[:i]]; ok {
p = append(p, s...)
} else {
j, _ := strconv.Atoi(template[:i])
if j >= len(subs) {
p = append(p, []byte("Missing")...)
} else {
p = append(p, subs[j]...)
}
}
template = template[i+1:]
}
p = append(p, template...)
return string(p)
}
// Reverse s string, support unicode
func Reverse(s string) string {
n := len(s)
runes := make([]rune, n)
for _, rune := range s {
n--
runes[n] = rune
}
return string(runes[n:])
}
// RandomCreateBytes generate random []byte by specify chars.
func RandomCreateBytes(n int, alphabets ...byte) []byte {
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var bytes = make([]byte, n)
var randby bool
if num, err := rand.Read(bytes); num != n || err != nil {
r.Seed(time.Now().UnixNano())
randby = true
}
for i, b := range bytes {
if len(alphabets) == 0 {
if randby {
bytes[i] = alphanum[r.Intn(len(alphanum))]
} else {
bytes[i] = alphanum[b%byte(len(alphanum))]
}
} else {
if randby {
bytes[i] = alphabets[r.Intn(len(alphabets))]
} else {
bytes[i] = alphabets[b%byte(len(alphabets))]
}
}
}
return bytes
}
// ToSnakeCase can convert all upper case characters in a string to
// underscore format.
//
// Some samples.
// "FirstName" => "first_name"
// "HTTPServer" => "http_server"
// "NoHTTPS" => "no_https"
// "GO_PATH" => "go_path"
// "GO PATH" => "go_path" // space is converted to underscore.
// "GO-PATH" => "go_path" // hyphen is converted to underscore.
//
// From https://github.com/huandu/xstrings
func ToSnakeCase(str string) string {
if len(str) == 0 {
return ""
}
buf := &bytes.Buffer{}
var prev, r0, r1 rune
var size int
r0 = '_'
for len(str) > 0 {
prev = r0
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]
switch {
case r0 == utf8.RuneError:
buf.WriteByte(byte(str[0]))
case unicode.IsUpper(r0):
if prev != '_' {
buf.WriteRune('_')
}
buf.WriteRune(unicode.ToLower(r0))
if len(str) == 0 {
break
}
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]
if !unicode.IsUpper(r0) {
buf.WriteRune(r0)
break
}
// find next non-upper-case character and insert `_` properly.
// it's designed to convert `HTTPServer` to `http_server`.
// if there are more than 2 adjacent upper case characters in a word,
// treat them as an abbreviation plus a normal word.
for len(str) > 0 {
r1 = r0
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]
if r0 == utf8.RuneError {
buf.WriteRune(unicode.ToLower(r1))
buf.WriteByte(byte(str[0]))
break
}
if !unicode.IsUpper(r0) {
if r0 == '_' || r0 == ' ' || r0 == '-' {
r0 = '_'
buf.WriteRune(unicode.ToLower(r1))
} else {
buf.WriteRune('_')
buf.WriteRune(unicode.ToLower(r1))
buf.WriteRune(r0)
}
break
}
buf.WriteRune(unicode.ToLower(r1))
}
if len(str) == 0 || r0 == '_' {
buf.WriteRune(unicode.ToLower(r0))
break
}
default:
if r0 == ' ' || r0 == '-' {
r0 = '_'
}
buf.WriteRune(r0)
}
}
return buf.String()
}

115
vendor/github.com/Unknwon/com/time.go generated vendored Normal file
View File

@ -0,0 +1,115 @@
// Copyright 2013 com 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 com
import (
"fmt"
"strconv"
"strings"
"time"
)
// Format unix time int64 to string
func Date(ti int64, format string) string {
t := time.Unix(int64(ti), 0)
return DateT(t, format)
}
// Format unix time string to string
func DateS(ts string, format string) string {
i, _ := strconv.ParseInt(ts, 10, 64)
return Date(i, format)
}
// Format time.Time struct to string
// MM - month - 01
// M - month - 1, single bit
// DD - day - 02
// D - day 2
// YYYY - year - 2006
// YY - year - 06
// HH - 24 hours - 03
// H - 24 hours - 3
// hh - 12 hours - 03
// h - 12 hours - 3
// mm - minute - 04
// m - minute - 4
// ss - second - 05
// s - second = 5
func DateT(t time.Time, format string) string {
res := strings.Replace(format, "MM", t.Format("01"), -1)
res = strings.Replace(res, "M", t.Format("1"), -1)
res = strings.Replace(res, "DD", t.Format("02"), -1)
res = strings.Replace(res, "D", t.Format("2"), -1)
res = strings.Replace(res, "YYYY", t.Format("2006"), -1)
res = strings.Replace(res, "YY", t.Format("06"), -1)
res = strings.Replace(res, "HH", fmt.Sprintf("%02d", t.Hour()), -1)
res = strings.Replace(res, "H", fmt.Sprintf("%d", t.Hour()), -1)
res = strings.Replace(res, "hh", t.Format("03"), -1)
res = strings.Replace(res, "h", t.Format("3"), -1)
res = strings.Replace(res, "mm", t.Format("04"), -1)
res = strings.Replace(res, "m", t.Format("4"), -1)
res = strings.Replace(res, "ss", t.Format("05"), -1)
res = strings.Replace(res, "s", t.Format("5"), -1)
return res
}
// DateFormat pattern rules.
var datePatterns = []string{
// year
"Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"y", "06", //A two digit representation of a year Examples: 99 or 03
// month
"m", "01", // Numeric representation of a month, with leading zeros 01 through 12
"n", "1", // Numeric representation of a month, without leading zeros 1 through 12
"M", "Jan", // A short textual representation of a month, three letters Jan through Dec
"F", "January", // A full textual representation of a month, such as January or March January through December
// day
"d", "02", // Day of the month, 2 digits with leading zeros 01 to 31
"j", "2", // Day of the month without leading zeros 1 to 31
// week
"D", "Mon", // A textual representation of a day, three letters Mon through Sun
"l", "Monday", // A full textual representation of the day of the week Sunday through Saturday
// time
"g", "3", // 12-hour format of an hour without leading zeros 1 through 12
"G", "15", // 24-hour format of an hour without leading zeros 0 through 23
"h", "03", // 12-hour format of an hour with leading zeros 01 through 12
"H", "15", // 24-hour format of an hour with leading zeros 00 through 23
"a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm
"A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM
"i", "04", // Minutes with leading zeros 00 to 59
"s", "05", // Seconds, with leading zeros 00 through 59
// time zone
"T", "MST",
"P", "-07:00",
"O", "-0700",
// RFC 2822
"r", time.RFC1123Z,
}
// Parse Date use PHP time format.
func DateParse(dateString, format string) (time.Time, error) {
replacer := strings.NewReplacer(datePatterns...)
format = replacer.Replace(format)
return time.ParseInLocation(format, dateString, time.Local)
}

41
vendor/github.com/Unknwon/com/url.go generated vendored Normal file
View File

@ -0,0 +1,41 @@
// Copyright 2013 com 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 com
import (
"encoding/base64"
"net/url"
)
// url encode string, is + not %20
func UrlEncode(str string) string {
return url.QueryEscape(str)
}
// url decode string
func UrlDecode(str string) (string, error) {
return url.QueryUnescape(str)
}
// base64 encode
func Base64Encode(str string) string {
return base64.StdEncoding.EncodeToString([]byte(str))
}
// base64 decode
func Base64Decode(str string) (string, error) {
s, e := base64.StdEncoding.DecodeString(str)
return string(s), e
}

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

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

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

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

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

@ -0,0 +1,671 @@
// 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())
}
errors = mapForm(formStruct, ctx.Req.Form, nil, errors)
validateAndMap(formStruct, ctx, errors, ifacePtr...)
}
}
// Maximum amount of memory to use when parsing a multipart form.
// Set this to whatever value you prefer; default is 10 MB.
var MaxMemory = int64(1024 * 1024 * 10)
// MultipartForm works much like Form, except it can parse multipart forms
// and handle file uploads. Like the other deserialization middleware handlers,
// you can pass in an interface to make the interface available for injection
// into other handlers later.
func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
return func(ctx *macaron.Context) {
var errors Errors
ensureNotPointer(formStruct)
formStruct := reflect.New(reflect.TypeOf(formStruct))
// This if check is necessary due to https://github.com/martini-contrib/csrf/issues/6
if ctx.Req.MultipartForm == nil {
// Workaround for multipart forms returning nil instead of an error
// when content is not multipart; see https://code.google.com/p/go/issues/detail?id=6334
if multipartReader, err := ctx.Req.MultipartReader(); err != nil {
errors.Add([]string{}, ERR_DESERIALIZATION, err.Error())
} else {
form, parseErr := multipartReader.ReadForm(MaxMemory)
if parseErr != nil {
errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error())
}
if ctx.Req.Form == nil {
ctx.Req.ParseForm()
}
for k, v := range form.Value {
ctx.Req.Form[k] = append(ctx.Req.Form[k], v...)
}
ctx.Req.MultipartForm = form
}
}
errors = mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
validateAndMap(formStruct, ctx, errors, ifacePtr...)
}
}
// Json is middleware to deserialize a JSON payload from the request
// into the struct that is passed in. The resulting struct is then
// validated, but no error handling is actually performed here.
// An interface pointer can be added as a second argument in order
// to map the struct to a specific interface.
func Json(jsonStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
return func(ctx *macaron.Context) {
var errors Errors
ensureNotPointer(jsonStruct)
jsonStruct := reflect.New(reflect.TypeOf(jsonStruct))
if ctx.Req.Request.Body != nil {
defer ctx.Req.Request.Body.Close()
err := json.NewDecoder(ctx.Req.Request.Body).Decode(jsonStruct.Interface())
if err != nil && err != io.EOF {
errors.Add([]string{}, ERR_DESERIALIZATION, err.Error())
}
}
validateAndMap(jsonStruct, ctx, errors, ifacePtr...)
}
}
// Validate is middleware to enforce required fields. If the struct
// passed in implements Validator, then the user-defined Validate method
// is executed, and its errors are mapped to the context. This middleware
// performs no error handling: it merely detects errors and maps them.
func Validate(obj interface{}) macaron.Handler {
return func(ctx *macaron.Context) {
var errors Errors
v := reflect.ValueOf(obj)
k := v.Kind()
if k == reflect.Interface || k == reflect.Ptr {
v = v.Elem()
k = v.Kind()
}
if k == reflect.Slice || k == reflect.Array {
for i := 0; i < v.Len(); i++ {
e := v.Index(i).Interface()
errors = validateStruct(errors, e)
if validator, ok := e.(Validator); ok {
errors = validator.Validate(ctx, errors)
}
}
} else {
errors = validateStruct(errors, obj)
if validator, ok := obj.(Validator); ok {
errors = validator.Validate(ctx, errors)
}
}
ctx.Map(errors)
}
}
var (
AlphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
AlphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
EmailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
URLPattern = regexp.MustCompile(`(http|https):\/\/(?:\\S+(?::\\S*)?@)?[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?`)
)
type (
// Rule represents a validation rule.
Rule struct {
// IsMatch checks if rule matches.
IsMatch func(string) bool
// IsValid applies validation rule to condition.
IsValid func(Errors, string, interface{}) (bool, Errors)
}
// RuleMapper represents a validation rule mapper,
// it allwos users to add custom validation rules.
RuleMapper []*Rule
)
var ruleMapper RuleMapper
// AddRule adds new validation rule.
func AddRule(r *Rule) {
ruleMapper = append(ruleMapper, r)
}
func in(fieldValue interface{}, arr string) bool {
val := fmt.Sprintf("%v", fieldValue)
vals := strings.Split(arr, ",")
isIn := false
for _, v := range vals {
if v == val {
isIn = true
break
}
}
return isIn
}
func parseFormName(raw, actual string) string {
if len(actual) > 0 {
return actual
}
return nameMapper(raw)
}
// Performs required field checking on a struct
func validateStruct(errors Errors, obj interface{}) Errors {
typ := reflect.TypeOf(obj)
val := reflect.ValueOf(obj)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
// Allow ignored fields in the struct
if field.Tag.Get("form") == "-" || !val.Field(i).CanInterface() {
continue
}
fieldVal := val.Field(i)
fieldValue := fieldVal.Interface()
zero := reflect.Zero(field.Type).Interface()
// Validate nested and embedded structs (if pointer, only do so if not nil)
if field.Type.Kind() == reflect.Struct ||
(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue) &&
field.Type.Elem().Kind() == reflect.Struct) {
errors = validateStruct(errors, fieldValue)
}
errors = validateField(errors, zero, field, fieldVal, fieldValue)
}
return errors
}
func validateField(errors Errors, zero interface{}, field reflect.StructField, fieldVal reflect.Value, fieldValue interface{}) Errors {
if fieldVal.Kind() == reflect.Slice {
for i := 0; i < fieldVal.Len(); i++ {
sliceVal := fieldVal.Index(i)
if sliceVal.Kind() == reflect.Ptr {
sliceVal = sliceVal.Elem()
}
sliceValue := sliceVal.Interface()
zero := reflect.Zero(sliceVal.Type()).Interface()
if sliceVal.Kind() == reflect.Struct ||
(sliceVal.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, sliceValue) &&
sliceVal.Elem().Kind() == reflect.Struct) {
errors = validateStruct(errors, sliceValue)
}
/* Apply validation rules to each item in a slice. ISSUE #3
else {
errors = validateField(errors, zero, field, sliceVal, sliceValue)
}*/
}
}
VALIDATE_RULES:
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
if len(rule) == 0 {
continue
}
switch {
case rule == "OmitEmpty":
if reflect.DeepEqual(zero, fieldValue) {
break VALIDATE_RULES
}
case rule == "Required":
if reflect.DeepEqual(zero, fieldValue) {
errors.Add([]string{field.Name}, ERR_REQUIRED, "Required")
break VALIDATE_RULES
}
case rule == "AlphaDash":
if AlphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
errors.Add([]string{field.Name}, ERR_ALPHA_DASH, "AlphaDash")
break VALIDATE_RULES
}
case rule == "AlphaDashDot":
if AlphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
errors.Add([]string{field.Name}, ERR_ALPHA_DASH_DOT, "AlphaDashDot")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "Size("):
size, _ := strconv.Atoi(rule[5 : len(rule)-1])
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) != size {
errors.Add([]string{field.Name}, ERR_SIZE, "Size")
break VALIDATE_RULES
}
v := reflect.ValueOf(fieldValue)
if v.Kind() == reflect.Slice && v.Len() != size {
errors.Add([]string{field.Name}, ERR_SIZE, "Size")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "MinSize("):
min, _ := strconv.Atoi(rule[8 : len(rule)-1])
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) < min {
errors.Add([]string{field.Name}, ERR_MIN_SIZE, "MinSize")
break VALIDATE_RULES
}
v := reflect.ValueOf(fieldValue)
if v.Kind() == reflect.Slice && v.Len() < min {
errors.Add([]string{field.Name}, ERR_MIN_SIZE, "MinSize")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "MaxSize("):
max, _ := strconv.Atoi(rule[8 : len(rule)-1])
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) > max {
errors.Add([]string{field.Name}, ERR_MAX_SIZE, "MaxSize")
break VALIDATE_RULES
}
v := reflect.ValueOf(fieldValue)
if v.Kind() == reflect.Slice && v.Len() > max {
errors.Add([]string{field.Name}, ERR_MAX_SIZE, "MaxSize")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "Range("):
nums := strings.Split(rule[6:len(rule)-1], ",")
if len(nums) != 2 {
break VALIDATE_RULES
}
val := com.StrTo(fmt.Sprintf("%v", fieldValue)).MustInt()
if val < com.StrTo(nums[0]).MustInt() || val > com.StrTo(nums[1]).MustInt() {
errors.Add([]string{field.Name}, ERR_RANGE, "Range")
break VALIDATE_RULES
}
case rule == "Email":
if !EmailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
errors.Add([]string{field.Name}, ERR_EMAIL, "Email")
break VALIDATE_RULES
}
case rule == "Url":
str := fmt.Sprintf("%v", fieldValue)
if len(str) == 0 {
continue
} else if !URLPattern.MatchString(str) {
errors.Add([]string{field.Name}, ERR_URL, "Url")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "In("):
if !in(fieldValue, rule[3:len(rule)-1]) {
errors.Add([]string{field.Name}, ERR_IN, "In")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "NotIn("):
if in(fieldValue, rule[6:len(rule)-1]) {
errors.Add([]string{field.Name}, ERR_NOT_INT, "NotIn")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "Include("):
if !strings.Contains(fmt.Sprintf("%v", fieldValue), rule[8:len(rule)-1]) {
errors.Add([]string{field.Name}, ERR_INCLUDE, "Include")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "Exclude("):
if strings.Contains(fmt.Sprintf("%v", fieldValue), rule[8:len(rule)-1]) {
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Exclude")
break VALIDATE_RULES
}
case strings.HasPrefix(rule, "Default("):
if reflect.DeepEqual(zero, fieldValue) {
if fieldVal.CanAddr() {
errors = setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
} else {
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Default")
break VALIDATE_RULES
}
}
default:
// Apply custom validation rules.
var isValid bool
for i := range ruleMapper {
if ruleMapper[i].IsMatch(rule) {
isValid, errors = ruleMapper[i].IsValid(errors, field.Name, fieldValue)
if !isValid {
break VALIDATE_RULES
}
}
}
}
}
return errors
}
// NameMapper represents a form tag name mapper.
type NameMapper func(string) string
var (
nameMapper = func(field string) string {
newstr := make([]rune, 0, len(field))
for i, chr := range field {
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
if i > 0 {
newstr = append(newstr, '_')
}
chr -= ('A' - 'a')
}
newstr = append(newstr, chr)
}
return string(newstr)
}
)
// SetNameMapper sets name mapper.
func SetNameMapper(nm NameMapper) {
nameMapper = nm
}
// Takes values from the form data and puts them into a struct
func mapForm(formStruct reflect.Value, form map[string][]string,
formfile map[string][]*multipart.FileHeader, errors Errors) Errors {
if formStruct.Kind() == reflect.Ptr {
formStruct = formStruct.Elem()
}
typ := formStruct.Type()
for i := 0; i < typ.NumField(); i++ {
typeField := typ.Field(i)
structField := formStruct.Field(i)
if typeField.Type.Kind() == reflect.Ptr && typeField.Anonymous {
structField.Set(reflect.New(typeField.Type.Elem()))
errors = mapForm(structField.Elem(), form, formfile, errors)
if reflect.DeepEqual(structField.Elem().Interface(), reflect.Zero(structField.Elem().Type()).Interface()) {
structField.Set(reflect.Zero(structField.Type()))
}
} else if typeField.Type.Kind() == reflect.Struct {
errors = mapForm(structField, form, formfile, errors)
}
inputFieldName := parseFormName(typeField.Name, typeField.Tag.Get("form"))
if len(inputFieldName) == 0 || !structField.CanSet() {
continue
}
inputValue, exists := form[inputFieldName]
if exists {
numElems := len(inputValue)
if structField.Kind() == reflect.Slice && numElems > 0 {
sliceOf := structField.Type().Elem().Kind()
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
for i := 0; i < numElems; i++ {
errors = setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
}
formStruct.Field(i).Set(slice)
} else {
errors = setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
}
continue
}
inputFile, exists := formfile[inputFieldName]
if !exists {
continue
}
fhType := reflect.TypeOf((*multipart.FileHeader)(nil))
numElems := len(inputFile)
if structField.Kind() == reflect.Slice && numElems > 0 && structField.Type().Elem() == fhType {
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
for i := 0; i < numElems; i++ {
slice.Index(i).Set(reflect.ValueOf(inputFile[i]))
}
structField.Set(slice)
} else if structField.Type() == fhType {
structField.Set(reflect.ValueOf(inputFile[0]))
}
}
return errors
}
// This sets the value in a struct of an indeterminate type to the
// matching value from the request (via Form middleware) in the
// same type, so that not all deserialized values have to be strings.
// Supported types are string, int, float, and bool.
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) Errors {
switch valueKind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if val == "" {
val = "0"
}
intVal, err := strconv.ParseInt(val, 10, 64)
if err != nil {
errors.Add([]string{nameInTag}, ERR_INTERGER_TYPE, "Value could not be parsed as integer")
} else {
structField.SetInt(intVal)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if val == "" {
val = "0"
}
uintVal, err := strconv.ParseUint(val, 10, 64)
if err != nil {
errors.Add([]string{nameInTag}, ERR_INTERGER_TYPE, "Value could not be parsed as unsigned integer")
} else {
structField.SetUint(uintVal)
}
case reflect.Bool:
if val == "on" {
structField.SetBool(true)
break
}
if val == "" {
val = "false"
}
boolVal, err := strconv.ParseBool(val)
if err != nil {
errors.Add([]string{nameInTag}, ERR_BOOLEAN_TYPE, "Value could not be parsed as boolean")
} else if boolVal {
structField.SetBool(true)
}
case reflect.Float32:
if val == "" {
val = "0.0"
}
floatVal, err := strconv.ParseFloat(val, 32)
if err != nil {
errors.Add([]string{nameInTag}, ERR_FLOAT_TYPE, "Value could not be parsed as 32-bit float")
} else {
structField.SetFloat(floatVal)
}
case reflect.Float64:
if val == "" {
val = "0.0"
}
floatVal, err := strconv.ParseFloat(val, 64)
if err != nil {
errors.Add([]string{nameInTag}, ERR_FLOAT_TYPE, "Value could not be parsed as 64-bit float")
} else {
structField.SetFloat(floatVal)
}
case reflect.String:
structField.SetString(val)
}
return errors
}
// Don't pass in pointers to bind to. Can lead to bugs.
func ensureNotPointer(obj interface{}) {
if reflect.TypeOf(obj).Kind() == reflect.Ptr {
panic("Pointers are not accepted as binding models")
}
}
// Performs validation and combines errors from validation
// with errors from deserialization, then maps both the
// resulting struct and the errors to the context.
func validateAndMap(obj reflect.Value, ctx *macaron.Context, errors Errors, ifacePtr ...interface{}) {
ctx.Invoke(Validate(obj.Interface()))
errors = append(errors, getErrors(ctx)...)
ctx.Map(errors)
ctx.Map(obj.Elem().Interface())
if len(ifacePtr) > 0 {
ctx.MapTo(obj.Elem().Interface(), ifacePtr[0])
}
}
// getErrors simply gets the errors from the context (it's kind of a chore)
func getErrors(ctx *macaron.Context) Errors {
return ctx.GetVal(reflect.TypeOf(Errors{})).Interface().(Errors)
}
type (
// ErrorHandler is the interface that has custom error handling process.
ErrorHandler interface {
// Error handles validation errors with custom process.
Error(*macaron.Context, Errors)
}
// Validator is the interface that handles some rudimentary
// request validation logic so your application doesn't have to.
Validator interface {
// Validate validates that the request is OK. It is recommended
// that validation be limited to checking values for syntax and
// semantics, enough to know that you can make sense of the request
// in your application. For example, you might verify that a credit
// card number matches a valid pattern, but you probably wouldn't
// perform an actual credit card authorization here.
Validate(*macaron.Context, Errors) Errors
}
)

159
vendor/github.com/go-macaron/binding/errors.go generated vendored Normal file
View File

@ -0,0 +1,159 @@
// Copyright 2014 Martini Authors
// Copyright 2014 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package binding
const (
// Type mismatch errors.
ERR_CONTENT_TYPE = "ContentTypeError"
ERR_DESERIALIZATION = "DeserializationError"
ERR_INTERGER_TYPE = "IntegerTypeError"
ERR_BOOLEAN_TYPE = "BooleanTypeError"
ERR_FLOAT_TYPE = "FloatTypeError"
// Validation errors.
ERR_REQUIRED = "RequiredError"
ERR_ALPHA_DASH = "AlphaDashError"
ERR_ALPHA_DASH_DOT = "AlphaDashDotError"
ERR_SIZE = "SizeError"
ERR_MIN_SIZE = "MinSizeError"
ERR_MAX_SIZE = "MaxSizeError"
ERR_RANGE = "RangeError"
ERR_EMAIL = "EmailError"
ERR_URL = "UrlError"
ERR_IN = "InError"
ERR_NOT_INT = "NotInError"
ERR_INCLUDE = "IncludeError"
ERR_EXCLUDE = "ExcludeError"
ERR_DEFAULT = "DefaultError"
)
type (
// Errors may be generated during deserialization, binding,
// or validation. This type is mapped to the context so you
// can inject it into your own handlers and use it in your
// application if you want all your errors to look the same.
Errors []Error
Error struct {
// An error supports zero or more field names, because an
// error can morph three ways: (1) it can indicate something
// wrong with the request as a whole, (2) it can point to a
// specific problem with a particular input field, or (3) it
// can span multiple related input fields.
FieldNames []string `json:"fieldNames,omitempty"`
// The classification is like an error code, convenient to
// use when processing or categorizing an error programmatically.
// It may also be called the "kind" of error.
Classification string `json:"classification,omitempty"`
// Message should be human-readable and detailed enough to
// pinpoint and resolve the problem, but it should be brief. For
// example, a payload of 100 objects in a JSON array might have
// an error in the 41st object. The message should help the
// end user find and fix the error with their request.
Message string `json:"message,omitempty"`
}
)
// Add adds an error associated with the fields indicated
// by fieldNames, with the given classification and message.
func (e *Errors) Add(fieldNames []string, classification, message string) {
*e = append(*e, Error{
FieldNames: fieldNames,
Classification: classification,
Message: message,
})
}
// Len returns the number of errors.
func (e *Errors) Len() int {
return len(*e)
}
// Has determines whether an Errors slice has an Error with
// a given classification in it; it does not search on messages
// or field names.
func (e *Errors) Has(class string) bool {
for _, err := range *e {
if err.Kind() == class {
return true
}
}
return false
}
/*
// WithClass gets a copy of errors that are classified by the
// the given classification.
func (e *Errors) WithClass(classification string) Errors {
var errs Errors
for _, err := range *e {
if err.Kind() == classification {
errs = append(errs, err)
}
}
return errs
}
// ForField gets a copy of errors that are associated with the
// field by the given name.
func (e *Errors) ForField(name string) Errors {
var errs Errors
for _, err := range *e {
for _, fieldName := range err.Fields() {
if fieldName == name {
errs = append(errs, err)
break
}
}
}
return errs
}
// Get gets errors of a particular class for the specified
// field name.
func (e *Errors) Get(class, fieldName string) Errors {
var errs Errors
for _, err := range *e {
if err.Kind() == class {
for _, nameOfField := range err.Fields() {
if nameOfField == fieldName {
errs = append(errs, err)
break
}
}
}
}
return errs
}
*/
// Fields returns the list of field names this error is
// associated with.
func (e Error) Fields() []string {
return e.FieldNames
}
// Kind returns this error's classification.
func (e Error) Kind() string {
return e.Classification
}
// Error returns this error's message.
func (e Error) Error() string {
return e.Message
}

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

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

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

@ -0,0 +1,18 @@
# csrf [![Build Status](https://travis-ci.org/go-macaron/csrf.svg?branch=master)](https://travis-ci.org/go-macaron/csrf) [![](http://gocover.io/_badge/github.com/go-macaron/csrf)](http://gocover.io/github.com/go-macaron/csrf)
Middleware csrf generates and validates CSRF tokens for [Macaron](https://github.com/go-macaron/macaron).
[API Reference](https://gowalker.org/github.com/go-macaron/csrf)
### Installation
go get github.com/go-macaron/csrf
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-macaron/csrf)
- [Documentation](http://go-macaron.com/docs/middlewares/csrf)
## License
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

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

@ -0,0 +1,262 @@
// 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 flag value used for the csrf token.
GetCookieHttpOnly() bool
// Return the token.
GetToken() string
// Validate by token.
ValidToken(t string) bool
// Error replies to the request with a custom function when ValidToken fails.
Error(w http.ResponseWriter)
}
type csrf struct {
// Header name value for setting and getting csrf token.
Header string
// Form name value for setting and getting csrf token.
Form string
// Cookie name value for setting and getting csrf token.
Cookie string
//Cookie path
CookiePath string
// Cookie HttpOnly flag value used for the csrf token.
CookieHttpOnly bool
// Token generated to pass via header, cookie, or hidden form value.
Token string
// This value must be unique per user.
ID string
// Secret used along with the unique id above to generate the Token.
Secret string
// ErrorFunc is the custom function that replies to the request when ValidToken fails.
ErrorFunc func(w http.ResponseWriter)
}
// GetHeaderName returns the name of the HTTP header for csrf token.
func (c *csrf) GetHeaderName() string {
return c.Header
}
// GetFormName returns the name of the form value for csrf token.
func (c *csrf) GetFormName() string {
return c.Form
}
// GetCookieName returns the name of the cookie for csrf token.
func (c *csrf) GetCookieName() string {
return c.Cookie
}
// GetCookiePath returns the path of the cookie for csrf token.
func (c *csrf) GetCookiePath() string {
return c.CookiePath
}
// GetCookieHttpOnly returns the flag value used for the csrf token.
func (c *csrf) GetCookieHttpOnly() bool {
return c.CookieHttpOnly
}
// GetToken returns the current token. This is typically used
// to populate a hidden form in an HTML template.
func (c *csrf) GetToken() string {
return c.Token
}
// ValidToken validates the passed token against the existing Secret and ID.
func (c *csrf) ValidToken(t string) bool {
return ValidToken(t, c.Secret, c.ID, "POST")
}
// Error replies to the request when ValidToken fails.
func (c *csrf) Error(w http.ResponseWriter) {
c.ErrorFunc(w)
}
// Options maintains options to manage behavior of Generate.
type Options struct {
// The global secret value used to generate Tokens.
Secret string
// HTTP header used to set and get token.
Header string
// Form value used to set and get token.
Form string
// Cookie value used to set and get token.
Cookie string
// Cookie path.
CookiePath string
CookieHttpOnly bool
// Key used for getting the unique ID per user.
SessionKey string
// oldSeesionKey saves old value corresponding to SessionKey.
oldSeesionKey string
// If true, send token via X-CSRFToken header.
SetHeader bool
// If true, send token via _csrf cookie.
SetCookie bool
// Set the Secure flag to true on the cookie.
Secure bool
// Disallow Origin appear in request header.
Origin bool
// The function called when Validate fails.
ErrorFunc func(w http.ResponseWriter)
}
func prepareOptions(options []Options) Options {
var opt Options
if len(options) > 0 {
opt = options[0]
}
// Defaults.
if len(opt.Secret) == 0 {
opt.Secret = string(com.RandomCreateBytes(10))
}
if len(opt.Header) == 0 {
opt.Header = "X-CSRFToken"
}
if len(opt.Form) == 0 {
opt.Form = "_csrf"
}
if len(opt.Cookie) == 0 {
opt.Cookie = "_csrf"
}
if len(opt.CookiePath) == 0 {
opt.CookiePath = "/"
}
if len(opt.SessionKey) == 0 {
opt.SessionKey = "uid"
}
opt.oldSeesionKey = "_old_" + opt.SessionKey
if opt.ErrorFunc == nil {
opt.ErrorFunc = func(w http.ResponseWriter) {
http.Error(w, "Invalid csrf token.", http.StatusBadRequest)
}
}
return opt
}
// Generate maps CSRF to each request. If this request is a Get request, it will generate a new token.
// Additionally, depending on options set, generated tokens will be sent via Header and/or Cookie.
func Generate(options ...Options) macaron.Handler {
opt := prepareOptions(options)
return func(ctx *macaron.Context, sess session.Store) {
x := &csrf{
Secret: opt.Secret,
Header: opt.Header,
Form: opt.Form,
Cookie: opt.Cookie,
CookiePath: opt.CookiePath,
CookieHttpOnly: opt.CookieHttpOnly,
ErrorFunc: opt.ErrorFunc,
}
ctx.MapTo(x, (*CSRF)(nil))
if opt.Origin && len(ctx.Req.Header.Get("Origin")) > 0 {
return
}
x.ID = "0"
uid := sess.Get(opt.SessionKey)
if uid != nil {
x.ID = com.ToStr(uid)
}
needsNew := false
oldUid := sess.Get(opt.oldSeesionKey)
if oldUid == nil || oldUid.(string) != x.ID {
needsNew = true
sess.Set(opt.oldSeesionKey, x.ID)
} else {
// If cookie present, map existing token, else generate a new one.
if val := ctx.GetCookie(opt.Cookie); len(val) > 0 {
// FIXME: test coverage.
x.Token = val
} else {
needsNew = true
}
}
if needsNew {
// FIXME: actionId.
x.Token = GenerateToken(x.Secret, x.ID, "POST")
if opt.SetCookie {
ctx.SetCookie(opt.Cookie, x.Token, 0, opt.CookiePath, "", false, opt.CookieHttpOnly, time.Now().AddDate(0, 0, 1))
}
}
if opt.SetHeader {
ctx.Resp.Header().Add(opt.Header, x.Token)
}
}
}
// Csrfer maps CSRF to each request. If this request is a Get request, it will generate a new token.
// Additionally, depending on options set, generated tokens will be sent via Header and/or Cookie.
func Csrfer(options ...Options) macaron.Handler {
return Generate(options...)
}
// Validate should be used as a per route middleware. It attempts to get a token from a "X-CSRFToken"
// HTTP header and then a "_csrf" form value. If one of these is found, the token will be validated
// using ValidToken. If this validation fails, custom Error is sent in the reply.
// If neither a header or form value is found, http.StatusBadRequest is sent.
func Validate(ctx *macaron.Context, x CSRF) {
if token := ctx.Req.Header.Get(x.GetHeaderName()); len(token) > 0 {
if !x.ValidToken(token) {
ctx.SetCookie(x.GetCookieName(), "", -1, x.GetCookiePath())
x.Error(ctx.Resp)
}
return
}
if token := ctx.Req.FormValue(x.GetFormName()); len(token) > 0 {
if !x.ValidToken(token) {
ctx.SetCookie(x.GetCookieName(), "", -1, x.GetCookiePath())
x.Error(ctx.Resp)
}
return
}
http.Error(ctx.Resp, "Bad Request: no CSRF token present", http.StatusBadRequest)
}

97
vendor/github.com/go-macaron/csrf/xsrf.go generated vendored Normal file
View File

@ -0,0 +1,97 @@
// Copyright 2012 Google Inc. All Rights Reserved.
// Copyright 2014 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package csrf
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"crypto/subtle"
"encoding/base64"
"fmt"
"strconv"
"strings"
"time"
)
// The duration that XSRF tokens are valid.
// It is exported so clients may set cookie timeouts that match generated tokens.
const TIMEOUT = 24 * time.Hour
// clean sanitizes a string for inclusion in a token by replacing all ":"s.
func clean(s string) string {
return strings.Replace(s, ":", "_", -1)
}
// GenerateToken returns a URL-safe secure XSRF token that expires in 24 hours.
//
// key is a secret key for your application.
// userID is a unique identifier for the user.
// actionID is the action the user is taking (e.g. POSTing to a particular path).
func GenerateToken(key, userID, actionID string) string {
return generateTokenAtTime(key, userID, actionID, time.Now())
}
// generateTokenAtTime is like Generate, but returns a token that expires 24 hours from now.
func generateTokenAtTime(key, userID, actionID string, now time.Time) string {
h := hmac.New(sha1.New, []byte(key))
fmt.Fprintf(h, "%s:%s:%d", clean(userID), clean(actionID), now.UnixNano())
tok := fmt.Sprintf("%s:%d", h.Sum(nil), now.UnixNano())
return base64.URLEncoding.EncodeToString([]byte(tok))
}
// Valid returns true if token is a valid, unexpired token returned by Generate.
func ValidToken(token, key, userID, actionID string) bool {
return validTokenAtTime(token, key, userID, actionID, time.Now())
}
// validTokenAtTime is like Valid, but it uses now to check if the token is expired.
func validTokenAtTime(token, key, userID, actionID string, now time.Time) bool {
// Decode the token.
data, err := base64.URLEncoding.DecodeString(token)
if err != nil {
return false
}
// Extract the issue time of the token.
sep := bytes.LastIndex(data, []byte{':'})
if sep < 0 {
return false
}
nanos, err := strconv.ParseInt(string(data[sep+1:]), 10, 64)
if err != nil {
return false
}
issueTime := time.Unix(0, nanos)
// Check that the token is not expired.
if now.Sub(issueTime) >= TIMEOUT {
return false
}
// Check that the token is not from the future.
// Allow 1 minute grace period in case the token is being verified on a
// machine whose clock is behind the machine that issued the token.
if issueTime.After(now.Add(1 * time.Minute)) {
return false
}
expected := generateTokenAtTime(key, userID, actionID, issueTime)
// Check that the token matches the expected value.
// Use constant time comparison to avoid timing attacks.
return subtle.ConstantTimeCompare([]byte(token), []byte(expected)) == 1
}

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

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

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

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

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

@ -0,0 +1,121 @@
// Copyright 2013 Martini Authors
// Copyright 2015 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package gzip
import (
"bufio"
"fmt"
"net"
"net/http"
"strings"
"github.com/klauspost/compress/gzip"
"gopkg.in/macaron.v1"
)
const (
_HEADER_ACCEPT_ENCODING = "Accept-Encoding"
_HEADER_CONTENT_ENCODING = "Content-Encoding"
_HEADER_CONTENT_LENGTH = "Content-Length"
_HEADER_CONTENT_TYPE = "Content-Type"
_HEADER_VARY = "Vary"
)
// Options represents a struct for specifying configuration options for the GZip middleware.
type Options struct {
// Compression level. Can be DefaultCompression(-1), ConstantCompression(-2)
// or any integer value between BestSpeed(1) and BestCompression(9) inclusive.
CompressionLevel int
}
func isCompressionLevelValid(level int) bool {
return level == gzip.DefaultCompression ||
level == gzip.ConstantCompression ||
(level >= gzip.BestSpeed && level <= gzip.BestCompression)
}
func prepareOptions(options []Options) Options {
var opt Options
if len(options) > 0 {
opt = options[0]
}
if !isCompressionLevelValid(opt.CompressionLevel) {
// For web content, level 4 seems to be a sweet spot.
opt.CompressionLevel = 4
}
return opt
}
// Gziper returns a Handler that adds gzip compression to all requests.
// Make sure to include the Gzip middleware above other middleware
// that alter the response body (like the render middleware).
func Gziper(options ...Options) macaron.Handler {
opt := prepareOptions(options)
return func(ctx *macaron.Context) {
if !strings.Contains(ctx.Req.Header.Get(_HEADER_ACCEPT_ENCODING), "gzip") {
return
}
headers := ctx.Resp.Header()
headers.Set(_HEADER_CONTENT_ENCODING, "gzip")
headers.Set(_HEADER_VARY, _HEADER_ACCEPT_ENCODING)
// We've made sure compression level is valid in prepareGzipOptions,
// no need to check same error again.
gz, err := gzip.NewWriterLevel(ctx.Resp, opt.CompressionLevel)
if err != nil {
panic(err.Error())
}
defer gz.Close()
gzw := gzipResponseWriter{gz, ctx.Resp}
ctx.Resp = gzw
ctx.MapTo(gzw, (*http.ResponseWriter)(nil))
// Check if render middleware has been registered,
// if yes, we need to modify ResponseWriter for it as well.
if _, ok := ctx.Render.(*macaron.DummyRender); !ok {
ctx.Render.SetResponseWriter(gzw)
}
ctx.Next()
// delete content length after we know we have been written to
gzw.Header().Del("Content-Length")
}
}
type gzipResponseWriter struct {
w *gzip.Writer
macaron.ResponseWriter
}
func (grw gzipResponseWriter) Write(p []byte) (int, error) {
if len(grw.Header().Get(_HEADER_CONTENT_TYPE)) == 0 {
grw.Header().Set(_HEADER_CONTENT_TYPE, http.DetectContentType(p))
}
return grw.w.Write(p)
}
func (grw gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := grw.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
}
return hijacker.Hijack()
}

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

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

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

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

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

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

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

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

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

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

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

@ -0,0 +1,261 @@
// Copyright 2013 Beego Authors
// Copyright 2014 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package session
import (
"fmt"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"sync"
"time"
"github.com/Unknwon/com"
)
// FileStore represents a file session store implementation.
type FileStore struct {
p *FileProvider
sid string
lock sync.RWMutex
data map[interface{}]interface{}
}
// NewFileStore creates and returns a file session store.
func NewFileStore(p *FileProvider, sid string, kv map[interface{}]interface{}) *FileStore {
return &FileStore{
p: p,
sid: sid,
data: kv,
}
}
// Set sets value to given key in session.
func (s *FileStore) Set(key, val interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
s.data[key] = val
return nil
}
// Get gets value by given key in session.
func (s *FileStore) Get(key interface{}) interface{} {
s.lock.RLock()
defer s.lock.RUnlock()
return s.data[key]
}
// Delete delete a key from session.
func (s *FileStore) Delete(key interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
delete(s.data, key)
return nil
}
// ID returns current session ID.
func (s *FileStore) ID() string {
return s.sid
}
// Release releases resource and save data to provider.
func (s *FileStore) Release() error {
s.p.lock.Lock()
defer s.p.lock.Unlock()
data, err := EncodeGob(s.data)
if err != nil {
return err
}
return ioutil.WriteFile(s.p.filepath(s.sid), data, os.ModePerm)
}
// Flush deletes all session data.
func (s *FileStore) Flush() error {
s.lock.Lock()
defer s.lock.Unlock()
s.data = make(map[interface{}]interface{})
return nil
}
// FileProvider represents a file session provider implementation.
type FileProvider struct {
lock sync.RWMutex
maxlifetime int64
rootPath string
}
// Init initializes file session provider with given root path.
func (p *FileProvider) Init(maxlifetime int64, rootPath string) error {
p.lock.Lock()
p.maxlifetime = maxlifetime
p.rootPath = rootPath
p.lock.Unlock()
return nil
}
func (p *FileProvider) filepath(sid string) string {
return path.Join(p.rootPath, string(sid[0]), string(sid[1]), sid)
}
// Read returns raw session store by session ID.
func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
filename := p.filepath(sid)
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
return nil, err
}
p.lock.RLock()
defer p.lock.RUnlock()
var f *os.File
if com.IsFile(filename) {
f, err = os.OpenFile(filename, os.O_RDWR, os.ModePerm)
} else {
f, err = os.Create(filename)
}
if err != nil {
return nil, err
}
defer f.Close()
if err = os.Chtimes(filename, time.Now(), time.Now()); err != nil {
return nil, err
}
var kv map[interface{}]interface{}
data, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
if len(data) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = DecodeGob(data)
if err != nil {
return nil, err
}
}
return NewFileStore(p, sid, kv), nil
}
// Exist returns true if session with given ID exists.
func (p *FileProvider) Exist(sid string) bool {
p.lock.RLock()
defer p.lock.RUnlock()
return com.IsFile(p.filepath(sid))
}
// Destory deletes a session by session ID.
func (p *FileProvider) Destory(sid string) error {
p.lock.Lock()
defer p.lock.Unlock()
return os.Remove(p.filepath(sid))
}
func (p *FileProvider) regenerate(oldsid, sid string) (err error) {
p.lock.Lock()
defer p.lock.Unlock()
filename := p.filepath(sid)
if com.IsExist(filename) {
return fmt.Errorf("new sid '%s' already exists", sid)
}
oldname := p.filepath(oldsid)
if !com.IsFile(oldname) {
data, err := EncodeGob(make(map[interface{}]interface{}))
if err != nil {
return err
}
if err = os.MkdirAll(path.Dir(oldname), os.ModePerm); err != nil {
return err
}
if err = ioutil.WriteFile(oldname, data, os.ModePerm); err != nil {
return err
}
}
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
return err
}
if err = os.Rename(oldname, filename); err != nil {
return err
}
return nil
}
// Regenerate regenerates a session store from old session ID to new one.
func (p *FileProvider) Regenerate(oldsid, sid string) (_ RawStore, err error) {
if err := p.regenerate(oldsid, sid); err != nil {
return nil, err
}
return p.Read(sid)
}
// Count counts and returns number of sessions.
func (p *FileProvider) Count() int {
count := 0
if err := filepath.Walk(p.rootPath, func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
if !fi.IsDir() {
count++
}
return nil
}); err != nil {
log.Printf("error counting session files: %v", err)
return 0
}
return count
}
// GC calls GC to clean expired sessions.
func (p *FileProvider) GC() {
p.lock.RLock()
defer p.lock.RUnlock()
if !com.IsExist(p.rootPath) {
return
}
if err := filepath.Walk(p.rootPath, func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
if !fi.IsDir() &&
(fi.ModTime().Unix()+p.maxlifetime) < time.Now().Unix() {
return os.Remove(path)
}
return nil
}); err != nil {
log.Printf("error garbage collecting session files: %v", err)
}
}
func init() {
Register("file", &FileProvider{})
}

217
vendor/github.com/go-macaron/session/memory.go generated vendored Normal file
View File

@ -0,0 +1,217 @@
// Copyright 2013 Beego Authors
// Copyright 2014 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package session
import (
"container/list"
"fmt"
"sync"
"time"
)
// MemStore represents a in-memory session store implementation.
type MemStore struct {
sid string
lock sync.RWMutex
data map[interface{}]interface{}
lastAccess time.Time
}
// NewMemStore creates and returns a memory session store.
func NewMemStore(sid string) *MemStore {
return &MemStore{
sid: sid,
data: make(map[interface{}]interface{}),
lastAccess: time.Now(),
}
}
// Set sets value to given key in session.
func (s *MemStore) Set(key, val interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
s.data[key] = val
return nil
}
// Get gets value by given key in session.
func (s *MemStore) Get(key interface{}) interface{} {
s.lock.RLock()
defer s.lock.RUnlock()
return s.data[key]
}
// Delete deletes a key from session.
func (s *MemStore) Delete(key interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
delete(s.data, key)
return nil
}
// ID returns current session ID.
func (s *MemStore) ID() string {
return s.sid
}
// Release releases resource and save data to provider.
func (_ *MemStore) Release() error {
return nil
}
// Flush deletes all session data.
func (s *MemStore) Flush() error {
s.lock.Lock()
defer s.lock.Unlock()
s.data = make(map[interface{}]interface{})
return nil
}
// MemProvider represents a in-memory session provider implementation.
type MemProvider struct {
lock sync.RWMutex
maxLifetime int64
data map[string]*list.Element
// A priority list whose lastAccess newer gets higer priority.
list *list.List
}
// Init initializes memory session provider.
func (p *MemProvider) Init(maxLifetime int64, _ string) error {
p.lock.Lock()
p.maxLifetime = maxLifetime
p.lock.Unlock()
return nil
}
// update expands time of session store by given ID.
func (p *MemProvider) update(sid string) error {
p.lock.Lock()
defer p.lock.Unlock()
if e, ok := p.data[sid]; ok {
e.Value.(*MemStore).lastAccess = time.Now()
p.list.MoveToFront(e)
return nil
}
return nil
}
// Read returns raw session store by session ID.
func (p *MemProvider) Read(sid string) (_ RawStore, err error) {
p.lock.RLock()
e, ok := p.data[sid]
p.lock.RUnlock()
if ok {
if err = p.update(sid); err != nil {
return nil, err
}
return e.Value.(*MemStore), nil
}
// Create a new session.
p.lock.Lock()
defer p.lock.Unlock()
s := NewMemStore(sid)
p.data[sid] = p.list.PushBack(s)
return s, nil
}
// Exist returns true if session with given ID exists.
func (p *MemProvider) Exist(sid string) bool {
p.lock.RLock()
defer p.lock.RUnlock()
_, ok := p.data[sid]
return ok
}
// Destory deletes a session by session ID.
func (p *MemProvider) Destory(sid string) error {
p.lock.Lock()
defer p.lock.Unlock()
e, ok := p.data[sid]
if !ok {
return nil
}
p.list.Remove(e)
delete(p.data, sid)
return nil
}
// Regenerate regenerates a session store from old session ID to new one.
func (p *MemProvider) Regenerate(oldsid, sid string) (RawStore, error) {
if p.Exist(sid) {
return nil, fmt.Errorf("new sid '%s' already exists", sid)
}
s, err := p.Read(oldsid)
if err != nil {
return nil, err
}
if err = p.Destory(oldsid); err != nil {
return nil, err
}
s.(*MemStore).sid = sid
p.lock.Lock()
defer p.lock.Unlock()
p.data[sid] = p.list.PushBack(s)
return s, nil
}
// Count counts and returns number of sessions.
func (p *MemProvider) Count() int {
return p.list.Len()
}
// GC calls GC to clean expired sessions.
func (p *MemProvider) GC() {
p.lock.RLock()
for {
// No session in the list.
e := p.list.Back()
if e == nil {
break
}
if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
p.lock.RUnlock()
p.lock.Lock()
p.list.Remove(e)
delete(p.data, e.Value.(*MemStore).sid)
p.lock.Unlock()
p.lock.RLock()
} else {
break
}
}
p.lock.RUnlock()
}
func init() {
Register("memory", &MemProvider{list: list.New(), data: make(map[string]*list.Element)})
}

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

@ -0,0 +1,399 @@
// Copyright 2013 Beego Authors
// Copyright 2014 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
// Package session a middleware that provides the session management of Macaron.
package session
import (
"encoding/hex"
"fmt"
"net/http"
"net/url"
"time"
"gopkg.in/macaron.v1"
)
const _VERSION = "0.3.0"
func Version() string {
return _VERSION
}
// RawStore is the interface that operates the session data.
type RawStore interface {
// Set sets value to given key in session.
Set(interface{}, interface{}) error
// Get gets value by given key in session.
Get(interface{}) interface{}
// Delete deletes a key from session.
Delete(interface{}) error
// ID returns current session ID.
ID() string
// Release releases session resource and save data to provider.
Release() error
// Flush deletes all session data.
Flush() error
}
// Store is the interface that contains all data for one session process with specific ID.
type Store interface {
RawStore
// Read returns raw session store by session ID.
Read(string) (RawStore, error)
// Destory deletes a session.
Destory(*macaron.Context) error
// RegenerateId regenerates a session store from old session ID to new one.
RegenerateId(*macaron.Context) (RawStore, error)
// Count counts and returns number of sessions.
Count() int
// GC calls GC to clean expired sessions.
GC()
}
type store struct {
RawStore
*Manager
}
var _ Store = &store{}
// Options represents a struct for specifying configuration options for the session middleware.
type Options struct {
// Name of provider. Default is "memory".
Provider string
// Provider configuration, it's corresponding to provider.
ProviderConfig string
// Cookie name to save session ID. Default is "MacaronSession".
CookieName string
// Cookie path to store. Default is "/".
CookiePath string
// GC interval time in seconds. Default is 3600.
Gclifetime int64
// Max life time in seconds. Default is whatever GC interval time is.
Maxlifetime int64
// Use HTTPS only. Default is false.
Secure bool
// Cookie life time. Default is 0.
CookieLifeTime int
// Cookie domain name. Default is empty.
Domain string
// Session ID length. Default is 16.
IDLength int
// Configuration section name. Default is "session".
Section string
}
func prepareOptions(options []Options) Options {
var opt Options
if len(options) > 0 {
opt = options[0]
}
if len(opt.Section) == 0 {
opt.Section = "session"
}
sec := macaron.Config().Section(opt.Section)
if len(opt.Provider) == 0 {
opt.Provider = sec.Key("PROVIDER").MustString("memory")
}
if len(opt.ProviderConfig) == 0 {
opt.ProviderConfig = sec.Key("PROVIDER_CONFIG").MustString("data/sessions")
}
if len(opt.CookieName) == 0 {
opt.CookieName = sec.Key("COOKIE_NAME").MustString("MacaronSession")
}
if len(opt.CookiePath) == 0 {
opt.CookiePath = sec.Key("COOKIE_PATH").MustString("/")
}
if opt.Gclifetime == 0 {
opt.Gclifetime = sec.Key("GC_INTERVAL_TIME").MustInt64(3600)
}
if opt.Maxlifetime == 0 {
opt.Maxlifetime = sec.Key("MAX_LIFE_TIME").MustInt64(opt.Gclifetime)
}
if !opt.Secure {
opt.Secure = sec.Key("SECURE").MustBool()
}
if opt.CookieLifeTime == 0 {
opt.CookieLifeTime = sec.Key("COOKIE_LIFE_TIME").MustInt()
}
if len(opt.Domain) == 0 {
opt.Domain = sec.Key("DOMAIN").String()
}
if opt.IDLength == 0 {
opt.IDLength = sec.Key("ID_LENGTH").MustInt(16)
}
return opt
}
// Sessioner is a middleware that maps a session.SessionStore service into the Macaron handler chain.
// An single variadic session.Options struct can be optionally provided to configure.
func Sessioner(options ...Options) macaron.Handler {
opt := prepareOptions(options)
manager, err := NewManager(opt.Provider, opt)
if err != nil {
panic(err)
}
go manager.startGC()
return func(ctx *macaron.Context) {
sess, err := manager.Start(ctx)
if err != nil {
panic("session(start): " + err.Error())
}
// Get flash.
vals, _ := url.ParseQuery(ctx.GetCookie("macaron_flash"))
if len(vals) > 0 {
f := &Flash{Values: vals}
f.ErrorMsg = f.Get("error")
f.SuccessMsg = f.Get("success")
f.InfoMsg = f.Get("info")
f.WarningMsg = f.Get("warning")
ctx.Data["Flash"] = f
ctx.SetCookie("macaron_flash", "", -1, opt.CookiePath)
}
f := &Flash{ctx, url.Values{}, "", "", "", ""}
ctx.Resp.Before(func(macaron.ResponseWriter) {
if flash := f.Encode(); len(flash) > 0 {
ctx.SetCookie("macaron_flash", flash, 0, opt.CookiePath)
}
})
ctx.Map(f)
s := store{
RawStore: sess,
Manager: manager,
}
ctx.MapTo(s, (*Store)(nil))
ctx.Next()
if err = sess.Release(); err != nil {
panic("session(release): " + err.Error())
}
}
}
// Provider is the interface that provides session manipulations.
type Provider interface {
// Init initializes session provider.
Init(gclifetime int64, config string) error
// Read returns raw session store by session ID.
Read(sid string) (RawStore, error)
// Exist returns true if session with given ID exists.
Exist(sid string) bool
// Destory deletes a session by session ID.
Destory(sid string) error
// Regenerate regenerates a session store from old session ID to new one.
Regenerate(oldsid, sid string) (RawStore, error)
// Count counts and returns number of sessions.
Count() int
// GC calls GC to clean expired sessions.
GC()
}
var providers = make(map[string]Provider)
// Register registers a provider.
func Register(name string, provider Provider) {
if provider == nil {
panic("session: cannot register provider with nil value")
}
if _, dup := providers[name]; dup {
panic(fmt.Errorf("session: cannot register provider '%s' twice", name))
}
providers[name] = provider
}
// _____
// / \ _____ ____ _____ ____ ___________
// / \ / \\__ \ / \\__ \ / ___\_/ __ \_ __ \
// / Y \/ __ \| | \/ __ \_/ /_/ > ___/| | \/
// \____|__ (____ /___| (____ /\___ / \___ >__|
// \/ \/ \/ \//_____/ \/
// Manager represents a struct that contains session provider and its configuration.
type Manager struct {
provider Provider
opt Options
}
// NewManager creates and returns a new session manager by given provider name and configuration.
// It panics when given provider isn't registered.
func NewManager(name string, opt Options) (*Manager, error) {
p, ok := providers[name]
if !ok {
return nil, fmt.Errorf("session: unknown provider '%s'(forgotten import?)", name)
}
return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig)
}
// sessionId generates a new session ID with rand string, unix nano time, remote addr by hash function.
func (m *Manager) sessionId() string {
return hex.EncodeToString(generateRandomKey(m.opt.IDLength / 2))
}
// Start starts a session by generating new one
// or retrieve existence one by reading session ID from HTTP request if it's valid.
func (m *Manager) Start(ctx *macaron.Context) (RawStore, error) {
sid := ctx.GetCookie(m.opt.CookieName)
if len(sid) > 0 && m.provider.Exist(sid) {
return m.provider.Read(sid)
}
sid = m.sessionId()
sess, err := m.provider.Read(sid)
if err != nil {
return nil, err
}
cookie := &http.Cookie{
Name: m.opt.CookieName,
Value: sid,
Path: m.opt.CookiePath,
HttpOnly: true,
Secure: m.opt.Secure,
Domain: m.opt.Domain,
}
if m.opt.CookieLifeTime >= 0 {
cookie.MaxAge = m.opt.CookieLifeTime
}
http.SetCookie(ctx.Resp, cookie)
ctx.Req.AddCookie(cookie)
return sess, nil
}
// Read returns raw session store by session ID.
func (m *Manager) Read(sid string) (RawStore, error) {
return m.provider.Read(sid)
}
// Destory deletes a session by given ID.
func (m *Manager) Destory(ctx *macaron.Context) error {
sid := ctx.GetCookie(m.opt.CookieName)
if len(sid) == 0 {
return nil
}
if err := m.provider.Destory(sid); err != nil {
return err
}
cookie := &http.Cookie{
Name: m.opt.CookieName,
Path: m.opt.CookiePath,
HttpOnly: true,
Expires: time.Now(),
MaxAge: -1,
}
http.SetCookie(ctx.Resp, cookie)
return nil
}
// RegenerateId regenerates a session store from old session ID to new one.
func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) {
sid := m.sessionId()
oldsid := ctx.GetCookie(m.opt.CookieName)
sess, err = m.provider.Regenerate(oldsid, sid)
if err != nil {
return nil, err
}
ck := &http.Cookie{
Name: m.opt.CookieName,
Value: sid,
Path: m.opt.CookiePath,
HttpOnly: true,
Secure: m.opt.Secure,
Domain: m.opt.Domain,
}
if m.opt.CookieLifeTime >= 0 {
ck.MaxAge = m.opt.CookieLifeTime
}
http.SetCookie(ctx.Resp, ck)
ctx.Req.AddCookie(ck)
return sess, nil
}
// Count counts and returns number of sessions.
func (m *Manager) Count() int {
return m.provider.Count()
}
// GC starts GC job in a certain period.
func (m *Manager) GC() {
m.provider.GC()
}
// startGC starts GC job in a certain period.
func (m *Manager) startGC() {
m.GC()
time.AfterFunc(time.Duration(m.opt.Gclifetime)*time.Second, func() { m.startGC() })
}
// SetSecure indicates whether to set cookie with HTTPS or not.
func (m *Manager) SetSecure(secure bool) {
m.opt.Secure = secure
}
// ___________.____ _____ _________ ___ ___
// \_ _____/| | / _ \ / _____// | \
// | __) | | / /_\ \ \_____ \/ ~ \
// | \ | |___/ | \/ \ Y /
// \___ / |_______ \____|__ /_______ /\___|_ /
// \/ \/ \/ \/ \/
type Flash struct {
ctx *macaron.Context
url.Values
ErrorMsg, WarningMsg, InfoMsg, SuccessMsg string
}
func (f *Flash) set(name, msg string, current ...bool) {
isShow := false
if (len(current) == 0 && macaron.FlashNow) ||
(len(current) > 0 && current[0]) {
isShow = true
}
if isShow {
f.ctx.Data["Flash"] = f
} else {
f.Set(name, msg)
}
}
func (f *Flash) Error(msg string, current ...bool) {
f.ErrorMsg = msg
f.set("error", msg, current...)
}
func (f *Flash) Warning(msg string, current ...bool) {
f.WarningMsg = msg
f.set("warning", msg, current...)
}
func (f *Flash) Info(msg string, current ...bool) {
f.InfoMsg = msg
f.set("info", msg, current...)
}
func (f *Flash) Success(msg string, current ...bool) {
f.SuccessMsg = msg
f.set("success", msg, current...)
}

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

@ -0,0 +1,60 @@
// Copyright 2013 Beego Authors
// Copyright 2014 The Macaron Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package session
import (
"bytes"
"crypto/rand"
"encoding/gob"
"io"
"github.com/Unknwon/com"
)
func init() {
gob.Register([]interface{}{})
gob.Register(map[int]interface{}{})
gob.Register(map[string]interface{}{})
gob.Register(map[interface{}]interface{}{})
gob.Register(map[string]string{})
gob.Register(map[int]string{})
gob.Register(map[int]int{})
gob.Register(map[int]int64{})
}
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
for _, v := range obj {
gob.Register(v)
}
buf := bytes.NewBuffer(nil)
err := gob.NewEncoder(buf).Encode(obj)
return buf.Bytes(), err
}
func DecodeGob(encoded []byte) (out map[interface{}]interface{}, err error) {
buf := bytes.NewBuffer(encoded)
err = gob.NewDecoder(buf).Decode(&out)
return out, err
}
// generateRandomKey creates a random key with the given strength.
func generateRandomKey(strength int) []byte {
k := make([]byte, strength)
if n, err := io.ReadFull(rand.Reader, k); n != strength || err != nil {
return com.RandomCreateBytes(strength)
}
return k
}

57
vendor/github.com/go-sql-driver/mysql/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,57 @@
# This is the official list of Go-MySQL-Driver authors for copyright purposes.
# If you are submitting a patch, please add your name or the name of the
# organization which holds the copyright to this list in alphabetical order.
# Names should be added to this file as
# Name <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
# Individual Persons
Aaron Hopkins <go-sql-driver at die.net>
Arne Hormann <arnehormann at gmail.com>
Carlos Nieto <jose.carlos at menteslibres.net>
Chris Moos <chris at tech9computers.com>
Daniel Nichter <nil at codenode.com>
Daniël van Eeden <git at myname.nl>
DisposaBoy <disposaboy at dby.me>
Egor Smolyakov <egorsmkv at gmail.com>
Frederick Mayle <frederickmayle at gmail.com>
Gustavo Kristic <gkristic at gmail.com>
Hanno Braun <mail at hannobraun.com>
Henri Yandell <flamefew at gmail.com>
Hirotaka Yamamoto <ymmt2005 at gmail.com>
INADA Naoki <songofacandy at gmail.com>
James Harr <james.harr at gmail.com>
Jian Zhen <zhenjl at gmail.com>
Joshua Prunier <joshua.prunier at gmail.com>
Julien Lefevre <julien.lefevr at gmail.com>
Julien Schmidt <go-sql-driver at julienschmidt.com>
Kamil Dziedzic <kamil at klecza.pl>
Kevin Malachowski <kevin at chowski.com>
Lennart Rudolph <lrudolph at hmc.edu>
Leonardo YongUk Kim <dalinaum at gmail.com>
Luca Looz <luca.looz92 at gmail.com>
Lucas Liu <extrafliu at gmail.com>
Luke Scott <luke at webconnex.com>
Michael Woolnough <michael.woolnough at gmail.com>
Nicola Peduzzi <thenikso at gmail.com>
Olivier Mengué <dolmen at cpan.org>
Paul Bonser <misterpib at gmail.com>
Runrioter Wung <runrioter at gmail.com>
Soroush Pour <me at soroushjp.com>
Stan Putrya <root.vagner at gmail.com>
Stanley Gunawan <gunawan.stanley at gmail.com>
Xiangyu Hu <xiangyu.hu at outlook.com>
Xiaobing Jiang <s7v7nislands at gmail.com>
Xiuming Chen <cc at cxm.cc>
Zhenye Xie <xiezhenye at gmail.com>
# Organizations
Barracuda Networks, Inc.
Google Inc.
Stripe Inc.

119
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,119 @@
## Version 1.3 (2016-12-01)
Changes:
- Go 1.1 is no longer supported
- Use decimals fields in MySQL to format time types (#249)
- Buffer optimizations (#269)
- TLS ServerName defaults to the host (#283)
- Refactoring (#400, #410, #437)
- Adjusted documentation for second generation CloudSQL (#485)
- Documented DSN system var quoting rules (#502)
- Made statement.Close() calls idempotent to avoid errors in Go 1.6+ (#512)
New Features:
- Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249)
- Support for returning table alias on Columns() (#289, #359, #382)
- Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318, #490)
- Support for uint64 parameters with high bit set (#332, #345)
- Cleartext authentication plugin support (#327)
- Exported ParseDSN function and the Config struct (#403, #419, #429)
- Read / Write timeouts (#401)
- Support for JSON field type (#414)
- Support for multi-statements and multi-results (#411, #431)
- DSN parameter to set the driver-side max_allowed_packet value manually (#489)
- Native password authentication plugin support (#494, #524)
Bugfixes:
- Fixed handling of queries without columns and rows (#255)
- Fixed a panic when SetKeepAlive() failed (#298)
- Handle ERR packets while reading rows (#321)
- Fixed reading NULL length-encoded integers in MySQL 5.6+ (#349)
- Fixed absolute paths support in LOAD LOCAL DATA INFILE (#356)
- Actually zero out bytes in handshake response (#378)
- Fixed race condition in registering LOAD DATA INFILE handler (#383)
- Fixed tests with MySQL 5.7.9+ (#380)
- QueryUnescape TLS config names (#397)
- Fixed "broken pipe" error by writing to closed socket (#390)
- Fixed LOAD LOCAL DATA INFILE buffering (#424)
- Fixed parsing of floats into float64 when placeholders are used (#434)
- Fixed DSN tests with Go 1.7+ (#459)
- Handle ERR packets while waiting for EOF (#473)
- Invalidate connection on error while discarding additional results (#513)
- Allow terminating packets of length 0 (#516)
## Version 1.2 (2014-06-03)
Changes:
- We switched back to a "rolling release". `go get` installs the current master branch again
- Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver
- Exported errors to allow easy checking from application code
- Enabled TCP Keepalives on TCP connections
- Optimized INFILE handling (better buffer size calculation, lazy init, ...)
- The DSN parser also checks for a missing separating slash
- Faster binary date / datetime to string formatting
- Also exported the MySQLWarning type
- mysqlConn.Close returns the first error encountered instead of ignoring all errors
- writePacket() automatically writes the packet size to the header
- readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets
New Features:
- `RegisterDial` allows the usage of a custom dial function to establish the network connection
- Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter
- Logging of critical errors is configurable with `SetLogger`
- Google CloudSQL support
Bugfixes:
- Allow more than 32 parameters in prepared statements
- Various old_password fixes
- Fixed TestConcurrent test to pass Go's race detection
- Fixed appendLengthEncodedInteger for large numbers
- Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo)
## Version 1.1 (2013-11-02)
Changes:
- Go-MySQL-Driver now requires Go 1.1
- Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore
- Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors
- `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")`
- DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'.
- Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries
- Optimized the buffer for reading
- stmt.Query now caches column metadata
- New Logo
- Changed the copyright header to include all contributors
- Improved the LOAD INFILE documentation
- The driver struct is now exported to make the driver directly accessible
- Refactored the driver tests
- Added more benchmarks and moved all to a separate file
- Other small refactoring
New Features:
- Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure
- Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs
- Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used
Bugfixes:
- Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification
- Convert to DB timezone when inserting `time.Time`
- Splitted packets (more than 16MB) are now merged correctly
- Fixed false positive `io.EOF` errors when the data was fully read
- Avoid panics on reuse of closed connections
- Fixed empty string producing false nil values
- Fixed sign byte for positive TIME fields
## Version 1.0 (2013-05-14)
Initial Release

23
vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,23 @@
# Contributing Guidelines
## Reporting Issues
Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed).
## Contributing Code
By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file.
Don't forget to add yourself to the AUTHORS file.
### Code Review
Everyone is invited to review and comment on pull requests.
If it looks fine to you, comment with "LGTM" (Looks good to me).
If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes.
Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM".
## Development Ideas
If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page.

373
vendor/github.com/go-sql-driver/mysql/LICENSE generated vendored Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

443
vendor/github.com/go-sql-driver/mysql/README.md generated vendored Normal file
View File

@ -0,0 +1,443 @@
# Go-MySQL-Driver
A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) package
![Go-MySQL-Driver logo](https://raw.github.com/wiki/go-sql-driver/mysql/gomysql_m.png "Golang Gopher holding the MySQL Dolphin")
---------------------------------------
* [Features](#features)
* [Requirements](#requirements)
* [Installation](#installation)
* [Usage](#usage)
* [DSN (Data Source Name)](#dsn-data-source-name)
* [Password](#password)
* [Protocol](#protocol)
* [Address](#address)
* [Parameters](#parameters)
* [Examples](#examples)
* [LOAD DATA LOCAL INFILE support](#load-data-local-infile-support)
* [time.Time support](#timetime-support)
* [Unicode support](#unicode-support)
* [Testing / Development](#testing--development)
* [License](#license)
---------------------------------------
## Features
* Lightweight and [fast](https://github.com/go-sql-driver/sql-benchmark "golang MySQL-Driver performance")
* Native Go implementation. No C-bindings, just pure Go
* Connections over TCP/IPv4, TCP/IPv6, Unix domain sockets or [custom protocols](https://godoc.org/github.com/go-sql-driver/mysql#DialFunc)
* Automatic handling of broken connections
* Automatic Connection Pooling *(by database/sql package)*
* Supports queries larger than 16MB
* Full [`sql.RawBytes`](https://golang.org/pkg/database/sql/#RawBytes) support.
* Intelligent `LONG DATA` handling in prepared statements
* Secure `LOAD DATA LOCAL INFILE` support with file Whitelisting and `io.Reader` support
* Optional `time.Time` parsing
* Optional placeholder interpolation
## Requirements
* Go 1.2 or higher
* MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+)
---------------------------------------
## Installation
Simple install the package to your [$GOPATH](https://github.com/golang/go/wiki/GOPATH "GOPATH") with the [go tool](https://golang.org/cmd/go/ "go command") from shell:
```bash
$ go get github.com/go-sql-driver/mysql
```
Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`.
## Usage
_Go MySQL Driver_ is an implementation of Go's `database/sql/driver` interface. You only need to import the driver and can use the full [`database/sql`](https://golang.org/pkg/database/sql/) API then.
Use `mysql` as `driverName` and a valid [DSN](#dsn-data-source-name) as `dataSourceName`:
```go
import "database/sql"
import _ "github.com/go-sql-driver/mysql"
db, err := sql.Open("mysql", "user:password@/dbname")
```
[Examples are available in our Wiki](https://github.com/go-sql-driver/mysql/wiki/Examples "Go-MySQL-Driver Examples").
### DSN (Data Source Name)
The Data Source Name has a common format, like e.g. [PEAR DB](http://pear.php.net/manual/en/package.database.db.intro-dsn.php) uses it, but without type-prefix (optional parts marked by squared brackets):
```
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
```
A DSN in its fullest form:
```
username:password@protocol(address)/dbname?param=value
```
Except for the databasename, all values are optional. So the minimal DSN is:
```
/dbname
```
If you do not want to preselect a database, leave `dbname` empty:
```
/
```
This has the same effect as an empty DSN string:
```
```
Alternatively, [Config.FormatDSN](https://godoc.org/github.com/go-sql-driver/mysql#Config.FormatDSN) can be used to create a DSN string by filling a struct.
#### Password
Passwords can consist of any character. Escaping is **not** necessary.
#### Protocol
See [net.Dial](https://golang.org/pkg/net/#Dial) for more information which networks are available.
In general you should use an Unix domain socket if available and TCP otherwise for best performance.
#### Address
For TCP and UDP networks, addresses have the form `host:port`.
If `host` is a literal IPv6 address, it must be enclosed in square brackets.
The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form.
For Unix domain sockets the address is the absolute path to the MySQL-Server-socket, e.g. `/var/run/mysqld/mysqld.sock` or `/tmp/mysql.sock`.
#### Parameters
*Parameters are case-sensitive!*
Notice that any of `true`, `TRUE`, `True` or `1` is accepted to stand for a true boolean value. Not surprisingly, false can be specified as any of: `false`, `FALSE`, `False` or `0`.
##### `allowAllFiles`
```
Type: bool
Valid Values: true, false
Default: false
```
`allowAllFiles=true` disables the file Whitelist for `LOAD DATA LOCAL INFILE` and allows *all* files.
[*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)
##### `allowCleartextPasswords`
```
Type: bool
Valid Values: true, false
Default: false
```
`allowCleartextPasswords=true` allows using the [cleartext client side plugin](http://dev.mysql.com/doc/en/cleartext-authentication-plugin.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network.
##### `allowNativePasswords`
```
Type: bool
Valid Values: true, false
Default: false
```
`allowNativePasswords=true` allows the usage of the mysql native password method.
##### `allowOldPasswords`
```
Type: bool
Valid Values: true, false
Default: false
```
`allowOldPasswords=true` allows the usage of the insecure old password method. This should be avoided, but is necessary in some cases. See also [the old_passwords wiki page](https://github.com/go-sql-driver/mysql/wiki/old_passwords).
##### `charset`
```
Type: string
Valid Values: <name>
Default: none
```
Sets the charset used for client-server interaction (`"SET NAMES <value>"`). If multiple charsets are set (separated by a comma), the following charset is used if setting the charset failes. This enables for example support for `utf8mb4` ([introduced in MySQL 5.5.3](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)) with fallback to `utf8` for older servers (`charset=utf8mb4,utf8`).
Usage of the `charset` parameter is discouraged because it issues additional queries to the server.
Unless you need the fallback behavior, please use `collation` instead.
##### `collation`
```
Type: string
Valid Values: <name>
Default: utf8_general_ci
```
Sets the collation used for client-server interaction on connection. In contrast to `charset`, `collation` does not issue additional queries. If the specified collation is unavailable on the target server, the connection will fail.
A list of valid charsets for a server is retrievable with `SHOW COLLATION`.
##### `clientFoundRows`
```
Type: bool
Valid Values: true, false
Default: false
```
`clientFoundRows=true` causes an UPDATE to return the number of matching rows instead of the number of rows changed.
##### `columnsWithAlias`
```
Type: bool
Valid Values: true, false
Default: false
```
When `columnsWithAlias` is true, calls to `sql.Rows.Columns()` will return the table alias and the column name separated by a dot. For example:
```
SELECT u.id FROM users as u
```
will return `u.id` instead of just `id` if `columnsWithAlias=true`.
##### `interpolateParams`
```
Type: bool
Valid Values: true, false
Default: false
```
If `interpolateParams` is true, placeholders (`?`) in calls to `db.Query()` and `db.Exec()` are interpolated into a single query string with given parameters. This reduces the number of roundtrips, since the driver has to prepare a statement, execute it with given parameters and close the statement again with `interpolateParams=false`.
*This can not be used together with the multibyte encodings BIG5, CP932, GB2312, GBK or SJIS. These are blacklisted as they may [introduce a SQL injection vulnerability](http://stackoverflow.com/a/12118602/3430118)!*
##### `loc`
```
Type: string
Valid Values: <escaped name>
Default: UTC
```
Sets the location for time.Time values (when using `parseTime=true`). *"Local"* sets the system's location. See [time.LoadLocation](https://golang.org/pkg/time/#LoadLocation) for details.
Note that this sets the location for time.Time values but does not change MySQL's [time_zone setting](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html). For that see the [time_zone system variable](#system-variables), which can also be set as a DSN parameter.
Please keep in mind, that param values must be [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)'ed. Alternatively you can manually replace the `/` with `%2F`. For example `US/Pacific` would be `loc=US%2FPacific`.
##### `maxAllowedPacket`
```
Type: decimal number
Default: 0
```
Max packet size allowed in bytes. Use `maxAllowedPacket=0` to automatically fetch the `max_allowed_packet` variable from server.
##### `multiStatements`
```
Type: bool
Valid Values: true, false
Default: false
```
Allow multiple statements in one query. While this allows batch queries, it also greatly increases the risk of SQL injections. Only the result of the first query is returned, all other results are silently discarded.
When `multiStatements` is used, `?` parameters must only be used in the first statement.
##### `parseTime`
```
Type: bool
Valid Values: true, false
Default: false
```
`parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string`
##### `readTimeout`
```
Type: decimal number
Default: 0
```
I/O read timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*.
##### `strict`
```
Type: bool
Valid Values: true, false
Default: false
```
`strict=true` enables a driver-side strict mode in which MySQL warnings are treated as errors. This mode should not be used in production as it may lead to data corruption in certain situations.
A server-side strict mode, which is safe for production use, can be set via the [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html) system variable.
By default MySQL also treats notes as warnings. Use [`sql_notes=false`](http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_sql_notes) to ignore notes.
##### `timeout`
```
Type: decimal number
Default: OS default
```
*Driver* side connection timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout).
##### `tls`
```
Type: bool / string
Valid Values: true, false, skip-verify, <name>
Default: false
```
`tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig).
##### `writeTimeout`
```
Type: decimal number
Default: 0
```
I/O write timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*.
##### System Variables
Any other parameters are interpreted as system variables:
* `<boolean_var>=<value>`: `SET <boolean_var>=<value>`
* `<enum_var>=<value>`: `SET <enum_var>=<value>`
* `<string_var>=%27<value>%27`: `SET <string_var>='<value>'`
Rules:
* The values for string variables must be quoted with '
* The values must also be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed!
(which implies values of string variables must be wrapped with `%27`)
Examples:
* `autocommit=1`: `SET autocommit=1`
* [`time_zone=%27Europe%2FParis%27`](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html): `SET time_zone='Europe/Paris'`
* [`tx_isolation=%27REPEATABLE-READ%27`](https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tx_isolation): `SET tx_isolation='REPEATABLE-READ'`
#### Examples
```
user@unix(/path/to/socket)/dbname
```
```
root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local
```
```
user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true
```
Treat warnings as errors by setting the system variable [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html):
```
user:password@/dbname?sql_mode=TRADITIONAL
```
TCP via IPv6:
```
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci
```
TCP on a remote host, e.g. Amazon RDS:
```
id:password@tcp(your-amazonaws-uri.com:3306)/dbname
```
Google Cloud SQL on App Engine (First Generation MySQL Server):
```
user@cloudsql(project-id:instance-name)/dbname
```
Google Cloud SQL on App Engine (Second Generation MySQL Server):
```
user@cloudsql(project-id:regionname:instance-name)/dbname
```
TCP using default port (3306) on localhost:
```
user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped
```
Use the default protocol (tcp) and host (localhost:3306):
```
user:password@/dbname
```
No Database preselected:
```
user:password@/
```
### `LOAD DATA LOCAL INFILE` support
For this feature you need direct access to the package. Therefore you must change the import path (no `_`):
```go
import "github.com/go-sql-driver/mysql"
```
Files must be whitelisted by registering them with `mysql.RegisterLocalFile(filepath)` (recommended) or the Whitelist check must be deactivated by using the DSN parameter `allowAllFiles=true` ([*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)).
To use a `io.Reader` a handler function must be registered with `mysql.RegisterReaderHandler(name, handler)` which returns a `io.Reader` or `io.ReadCloser`. The Reader is available with the filepath `Reader::<name>` then. Choose different names for different handlers and `DeregisterReaderHandler` when you don't need it anymore.
See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details.
### `time.Time` support
The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your programm.
However, many want to scan MySQL `DATE` and `DATETIME` values into `time.Time` variables, which is the logical opposite in Go to `DATE` and `DATETIME` in MySQL. You can do that by changing the internal output type from `[]byte` to `time.Time` with the DSN parameter `parseTime=true`. You can set the default [`time.Time` location](https://golang.org/pkg/time/#Location) with the `loc` DSN parameter.
**Caution:** As of Go 1.1, this makes `time.Time` the only variable type you can scan `DATE` and `DATETIME` values into. This breaks for example [`sql.RawBytes` support](https://github.com/go-sql-driver/mysql/wiki/Examples#rawbytes).
Alternatively you can use the [`NullTime`](https://godoc.org/github.com/go-sql-driver/mysql#NullTime) type as the scan destination, which works with both `time.Time` and `string` / `[]byte`.
### Unicode support
Since version 1.1 Go-MySQL-Driver automatically uses the collation `utf8_general_ci` by default.
Other collations / charsets can be set using the [`collation`](#collation) DSN parameter.
Version 1.0 of the driver recommended adding `&charset=utf8` (alias for `SET NAMES utf8`) to the DSN to enable proper UTF-8 support. This is not necessary anymore. The [`collation`](#collation) parameter should be preferred to set another collation / charset than the default.
See http://dev.mysql.com/doc/refman/5.7/en/charset-unicode.html for more details on MySQL's Unicode support.
## Testing / Development
To run the driver tests you may need to adjust the configuration. See the [Testing Wiki-Page](https://github.com/go-sql-driver/mysql/wiki/Testing "Testing") for details.
Go-MySQL-Driver is not feature-complete yet. Your help is very appreciated.
If you want to contribute, you can work on an [open issue](https://github.com/go-sql-driver/mysql/issues?state=open) or review a [pull request](https://github.com/go-sql-driver/mysql/pulls).
See the [Contribution Guidelines](https://github.com/go-sql-driver/mysql/blob/master/CONTRIBUTING.md) for details.
---------------------------------------
## License
Go-MySQL-Driver is licensed under the [Mozilla Public License Version 2.0](https://raw.github.com/go-sql-driver/mysql/master/LICENSE)
Mozilla summarizes the license scope as follows:
> MPL: The copyleft applies to any files containing MPLed code.
That means:
* You can **use** the **unchanged** source code both in private and commercially
* When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0)
* You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**
Please read the [MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/) if you have further questions regarding the license.
You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE)
![Go Gopher and MySQL Dolphin](https://raw.github.com/wiki/go-sql-driver/mysql/go-mysql-driver_m.jpg "Golang Gopher transporting the MySQL Dolphin in a wheelbarrow")

19
vendor/github.com/go-sql-driver/mysql/appengine.go generated vendored Normal file
View File

@ -0,0 +1,19 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build appengine
package mysql
import (
"appengine/cloudsql"
)
func init() {
RegisterDial("cloudsql", cloudsql.Dial)
}

147
vendor/github.com/go-sql-driver/mysql/buffer.go generated vendored Normal file
View File

@ -0,0 +1,147 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"io"
"net"
"time"
)
const defaultBufSize = 4096
// A buffer which is used for both reading and writing.
// This is possible since communication on each connection is synchronous.
// In other words, we can't write and read simultaneously on the same connection.
// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
// Also highly optimized for this particular use case.
type buffer struct {
buf []byte
nc net.Conn
idx int
length int
timeout time.Duration
}
func newBuffer(nc net.Conn) buffer {
var b [defaultBufSize]byte
return buffer{
buf: b[:],
nc: nc,
}
}
// fill reads into the buffer until at least _need_ bytes are in it
func (b *buffer) fill(need int) error {
n := b.length
// move existing data to the beginning
if n > 0 && b.idx > 0 {
copy(b.buf[0:n], b.buf[b.idx:])
}
// grow buffer if necessary
// TODO: let the buffer shrink again at some point
// Maybe keep the org buf slice and swap back?
if need > len(b.buf) {
// Round up to the next multiple of the default size
newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize)
copy(newBuf, b.buf)
b.buf = newBuf
}
b.idx = 0
for {
if b.timeout > 0 {
if err := b.nc.SetReadDeadline(time.Now().Add(b.timeout)); err != nil {
return err
}
}
nn, err := b.nc.Read(b.buf[n:])
n += nn
switch err {
case nil:
if n < need {
continue
}
b.length = n
return nil
case io.EOF:
if n >= need {
b.length = n
return nil
}
return io.ErrUnexpectedEOF
default:
return err
}
}
}
// returns next N bytes from buffer.
// The returned slice is only guaranteed to be valid until the next read
func (b *buffer) readNext(need int) ([]byte, error) {
if b.length < need {
// refill
if err := b.fill(need); err != nil {
return nil, err
}
}
offset := b.idx
b.idx += need
b.length -= need
return b.buf[offset:b.idx], nil
}
// returns a buffer with the requested size.
// If possible, a slice from the existing buffer is returned.
// Otherwise a bigger buffer is made.
// Only one buffer (total) can be used at a time.
func (b *buffer) takeBuffer(length int) []byte {
if b.length > 0 {
return nil
}
// test (cheap) general case first
if length <= defaultBufSize || length <= cap(b.buf) {
return b.buf[:length]
}
if length < maxPacketSize {
b.buf = make([]byte, length)
return b.buf
}
return make([]byte, length)
}
// shortcut which can be used if the requested buffer is guaranteed to be
// smaller than defaultBufSize
// Only one buffer (total) can be used at a time.
func (b *buffer) takeSmallBuffer(length int) []byte {
if b.length == 0 {
return b.buf[:length]
}
return nil
}
// takeCompleteBuffer returns the complete existing buffer.
// This can be used if the necessary buffer size is unknown.
// Only one buffer (total) can be used at a time.
func (b *buffer) takeCompleteBuffer() []byte {
if b.length == 0 {
return b.buf
}
return nil
}

250
vendor/github.com/go-sql-driver/mysql/collations.go generated vendored Normal file
View File

@ -0,0 +1,250 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2014 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
const defaultCollation = "utf8_general_ci"
// A list of available collations mapped to the internal ID.
// To update this map use the following MySQL query:
// SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS
var collations = map[string]byte{
"big5_chinese_ci": 1,
"latin2_czech_cs": 2,
"dec8_swedish_ci": 3,
"cp850_general_ci": 4,
"latin1_german1_ci": 5,
"hp8_english_ci": 6,
"koi8r_general_ci": 7,
"latin1_swedish_ci": 8,
"latin2_general_ci": 9,
"swe7_swedish_ci": 10,
"ascii_general_ci": 11,
"ujis_japanese_ci": 12,
"sjis_japanese_ci": 13,
"cp1251_bulgarian_ci": 14,
"latin1_danish_ci": 15,
"hebrew_general_ci": 16,
"tis620_thai_ci": 18,
"euckr_korean_ci": 19,
"latin7_estonian_cs": 20,
"latin2_hungarian_ci": 21,
"koi8u_general_ci": 22,
"cp1251_ukrainian_ci": 23,
"gb2312_chinese_ci": 24,
"greek_general_ci": 25,
"cp1250_general_ci": 26,
"latin2_croatian_ci": 27,
"gbk_chinese_ci": 28,
"cp1257_lithuanian_ci": 29,
"latin5_turkish_ci": 30,
"latin1_german2_ci": 31,
"armscii8_general_ci": 32,
"utf8_general_ci": 33,
"cp1250_czech_cs": 34,
"ucs2_general_ci": 35,
"cp866_general_ci": 36,
"keybcs2_general_ci": 37,
"macce_general_ci": 38,
"macroman_general_ci": 39,
"cp852_general_ci": 40,
"latin7_general_ci": 41,
"latin7_general_cs": 42,
"macce_bin": 43,
"cp1250_croatian_ci": 44,
"utf8mb4_general_ci": 45,
"utf8mb4_bin": 46,
"latin1_bin": 47,
"latin1_general_ci": 48,
"latin1_general_cs": 49,
"cp1251_bin": 50,
"cp1251_general_ci": 51,
"cp1251_general_cs": 52,
"macroman_bin": 53,
"utf16_general_ci": 54,
"utf16_bin": 55,
"utf16le_general_ci": 56,
"cp1256_general_ci": 57,
"cp1257_bin": 58,
"cp1257_general_ci": 59,
"utf32_general_ci": 60,
"utf32_bin": 61,
"utf16le_bin": 62,
"binary": 63,
"armscii8_bin": 64,
"ascii_bin": 65,
"cp1250_bin": 66,
"cp1256_bin": 67,
"cp866_bin": 68,
"dec8_bin": 69,
"greek_bin": 70,
"hebrew_bin": 71,
"hp8_bin": 72,
"keybcs2_bin": 73,
"koi8r_bin": 74,
"koi8u_bin": 75,
"latin2_bin": 77,
"latin5_bin": 78,
"latin7_bin": 79,
"cp850_bin": 80,
"cp852_bin": 81,
"swe7_bin": 82,
"utf8_bin": 83,
"big5_bin": 84,
"euckr_bin": 85,
"gb2312_bin": 86,
"gbk_bin": 87,
"sjis_bin": 88,
"tis620_bin": 89,
"ucs2_bin": 90,
"ujis_bin": 91,
"geostd8_general_ci": 92,
"geostd8_bin": 93,
"latin1_spanish_ci": 94,
"cp932_japanese_ci": 95,
"cp932_bin": 96,
"eucjpms_japanese_ci": 97,
"eucjpms_bin": 98,
"cp1250_polish_ci": 99,
"utf16_unicode_ci": 101,
"utf16_icelandic_ci": 102,
"utf16_latvian_ci": 103,
"utf16_romanian_ci": 104,
"utf16_slovenian_ci": 105,
"utf16_polish_ci": 106,
"utf16_estonian_ci": 107,
"utf16_spanish_ci": 108,
"utf16_swedish_ci": 109,
"utf16_turkish_ci": 110,
"utf16_czech_ci": 111,
"utf16_danish_ci": 112,
"utf16_lithuanian_ci": 113,
"utf16_slovak_ci": 114,
"utf16_spanish2_ci": 115,
"utf16_roman_ci": 116,
"utf16_persian_ci": 117,
"utf16_esperanto_ci": 118,
"utf16_hungarian_ci": 119,
"utf16_sinhala_ci": 120,
"utf16_german2_ci": 121,
"utf16_croatian_ci": 122,
"utf16_unicode_520_ci": 123,
"utf16_vietnamese_ci": 124,
"ucs2_unicode_ci": 128,
"ucs2_icelandic_ci": 129,
"ucs2_latvian_ci": 130,
"ucs2_romanian_ci": 131,
"ucs2_slovenian_ci": 132,
"ucs2_polish_ci": 133,
"ucs2_estonian_ci": 134,
"ucs2_spanish_ci": 135,
"ucs2_swedish_ci": 136,
"ucs2_turkish_ci": 137,
"ucs2_czech_ci": 138,
"ucs2_danish_ci": 139,
"ucs2_lithuanian_ci": 140,
"ucs2_slovak_ci": 141,
"ucs2_spanish2_ci": 142,
"ucs2_roman_ci": 143,
"ucs2_persian_ci": 144,
"ucs2_esperanto_ci": 145,
"ucs2_hungarian_ci": 146,
"ucs2_sinhala_ci": 147,
"ucs2_german2_ci": 148,
"ucs2_croatian_ci": 149,
"ucs2_unicode_520_ci": 150,
"ucs2_vietnamese_ci": 151,
"ucs2_general_mysql500_ci": 159,
"utf32_unicode_ci": 160,
"utf32_icelandic_ci": 161,
"utf32_latvian_ci": 162,
"utf32_romanian_ci": 163,
"utf32_slovenian_ci": 164,
"utf32_polish_ci": 165,
"utf32_estonian_ci": 166,
"utf32_spanish_ci": 167,
"utf32_swedish_ci": 168,
"utf32_turkish_ci": 169,
"utf32_czech_ci": 170,
"utf32_danish_ci": 171,
"utf32_lithuanian_ci": 172,
"utf32_slovak_ci": 173,
"utf32_spanish2_ci": 174,
"utf32_roman_ci": 175,
"utf32_persian_ci": 176,
"utf32_esperanto_ci": 177,
"utf32_hungarian_ci": 178,
"utf32_sinhala_ci": 179,
"utf32_german2_ci": 180,
"utf32_croatian_ci": 181,
"utf32_unicode_520_ci": 182,
"utf32_vietnamese_ci": 183,
"utf8_unicode_ci": 192,
"utf8_icelandic_ci": 193,
"utf8_latvian_ci": 194,
"utf8_romanian_ci": 195,
"utf8_slovenian_ci": 196,
"utf8_polish_ci": 197,
"utf8_estonian_ci": 198,
"utf8_spanish_ci": 199,
"utf8_swedish_ci": 200,
"utf8_turkish_ci": 201,
"utf8_czech_ci": 202,
"utf8_danish_ci": 203,
"utf8_lithuanian_ci": 204,
"utf8_slovak_ci": 205,
"utf8_spanish2_ci": 206,
"utf8_roman_ci": 207,
"utf8_persian_ci": 208,
"utf8_esperanto_ci": 209,
"utf8_hungarian_ci": 210,
"utf8_sinhala_ci": 211,
"utf8_german2_ci": 212,
"utf8_croatian_ci": 213,
"utf8_unicode_520_ci": 214,
"utf8_vietnamese_ci": 215,
"utf8_general_mysql500_ci": 223,
"utf8mb4_unicode_ci": 224,
"utf8mb4_icelandic_ci": 225,
"utf8mb4_latvian_ci": 226,
"utf8mb4_romanian_ci": 227,
"utf8mb4_slovenian_ci": 228,
"utf8mb4_polish_ci": 229,
"utf8mb4_estonian_ci": 230,
"utf8mb4_spanish_ci": 231,
"utf8mb4_swedish_ci": 232,
"utf8mb4_turkish_ci": 233,
"utf8mb4_czech_ci": 234,
"utf8mb4_danish_ci": 235,
"utf8mb4_lithuanian_ci": 236,
"utf8mb4_slovak_ci": 237,
"utf8mb4_spanish2_ci": 238,
"utf8mb4_roman_ci": 239,
"utf8mb4_persian_ci": 240,
"utf8mb4_esperanto_ci": 241,
"utf8mb4_hungarian_ci": 242,
"utf8mb4_sinhala_ci": 243,
"utf8mb4_german2_ci": 244,
"utf8mb4_croatian_ci": 245,
"utf8mb4_unicode_520_ci": 246,
"utf8mb4_vietnamese_ci": 247,
}
// A blacklist of collations which is unsafe to interpolate parameters.
// These multibyte encodings may contains 0x5c (`\`) in their trailing bytes.
var unsafeCollations = map[string]bool{
"big5_chinese_ci": true,
"sjis_japanese_ci": true,
"gbk_chinese_ci": true,
"big5_bin": true,
"gb2312_bin": true,
"gbk_bin": true,
"sjis_bin": true,
"cp932_japanese_ci": true,
"cp932_bin": true,
}

377
vendor/github.com/go-sql-driver/mysql/connection.go generated vendored Normal file
View File

@ -0,0 +1,377 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"net"
"strconv"
"strings"
"time"
)
type mysqlConn struct {
buf buffer
netConn net.Conn
affectedRows uint64
insertId uint64
cfg *Config
maxAllowedPacket int
maxWriteSize int
writeTimeout time.Duration
flags clientFlag
status statusFlag
sequence uint8
parseTime bool
strict bool
}
// Handles parameters set in DSN after the connection is established
func (mc *mysqlConn) handleParams() (err error) {
for param, val := range mc.cfg.Params {
switch param {
// Charset
case "charset":
charsets := strings.Split(val, ",")
for i := range charsets {
// ignore errors here - a charset may not exist
err = mc.exec("SET NAMES " + charsets[i])
if err == nil {
break
}
}
if err != nil {
return
}
// System Vars
default:
err = mc.exec("SET " + param + "=" + val + "")
if err != nil {
return
}
}
}
return
}
func (mc *mysqlConn) Begin() (driver.Tx, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
err := mc.exec("START TRANSACTION")
if err == nil {
return &mysqlTx{mc}, err
}
return nil, err
}
func (mc *mysqlConn) Close() (err error) {
// Makes Close idempotent
if mc.netConn != nil {
err = mc.writeCommandPacket(comQuit)
}
mc.cleanup()
return
}
// Closes the network connection and unsets internal variables. Do not call this
// function after successfully authentication, call Close instead. This function
// is called before auth or on auth failure because MySQL will have already
// closed the network connection.
func (mc *mysqlConn) cleanup() {
// Makes cleanup idempotent
if mc.netConn != nil {
if err := mc.netConn.Close(); err != nil {
errLog.Print(err)
}
mc.netConn = nil
}
mc.cfg = nil
mc.buf.nc = nil
}
func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
// Send command
err := mc.writeCommandPacketStr(comStmtPrepare, query)
if err != nil {
return nil, err
}
stmt := &mysqlStmt{
mc: mc,
}
// Read Result
columnCount, err := stmt.readPrepareResultPacket()
if err == nil {
if stmt.paramCount > 0 {
if err = mc.readUntilEOF(); err != nil {
return nil, err
}
}
if columnCount > 0 {
err = mc.readUntilEOF()
}
}
return stmt, err
}
func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (string, error) {
// Number of ? should be same to len(args)
if strings.Count(query, "?") != len(args) {
return "", driver.ErrSkip
}
buf := mc.buf.takeCompleteBuffer()
if buf == nil {
// can not take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer)
return "", driver.ErrBadConn
}
buf = buf[:0]
argPos := 0
for i := 0; i < len(query); i++ {
q := strings.IndexByte(query[i:], '?')
if q == -1 {
buf = append(buf, query[i:]...)
break
}
buf = append(buf, query[i:i+q]...)
i += q
arg := args[argPos]
argPos++
if arg == nil {
buf = append(buf, "NULL"...)
continue
}
switch v := arg.(type) {
case int64:
buf = strconv.AppendInt(buf, v, 10)
case float64:
buf = strconv.AppendFloat(buf, v, 'g', -1, 64)
case bool:
if v {
buf = append(buf, '1')
} else {
buf = append(buf, '0')
}
case time.Time:
if v.IsZero() {
buf = append(buf, "'0000-00-00'"...)
} else {
v := v.In(mc.cfg.Loc)
v = v.Add(time.Nanosecond * 500) // To round under microsecond
year := v.Year()
year100 := year / 100
year1 := year % 100
month := v.Month()
day := v.Day()
hour := v.Hour()
minute := v.Minute()
second := v.Second()
micro := v.Nanosecond() / 1000
buf = append(buf, []byte{
'\'',
digits10[year100], digits01[year100],
digits10[year1], digits01[year1],
'-',
digits10[month], digits01[month],
'-',
digits10[day], digits01[day],
' ',
digits10[hour], digits01[hour],
':',
digits10[minute], digits01[minute],
':',
digits10[second], digits01[second],
}...)
if micro != 0 {
micro10000 := micro / 10000
micro100 := micro / 100 % 100
micro1 := micro % 100
buf = append(buf, []byte{
'.',
digits10[micro10000], digits01[micro10000],
digits10[micro100], digits01[micro100],
digits10[micro1], digits01[micro1],
}...)
}
buf = append(buf, '\'')
}
case []byte:
if v == nil {
buf = append(buf, "NULL"...)
} else {
buf = append(buf, "_binary'"...)
if mc.status&statusNoBackslashEscapes == 0 {
buf = escapeBytesBackslash(buf, v)
} else {
buf = escapeBytesQuotes(buf, v)
}
buf = append(buf, '\'')
}
case string:
buf = append(buf, '\'')
if mc.status&statusNoBackslashEscapes == 0 {
buf = escapeStringBackslash(buf, v)
} else {
buf = escapeStringQuotes(buf, v)
}
buf = append(buf, '\'')
default:
return "", driver.ErrSkip
}
if len(buf)+4 > mc.maxAllowedPacket {
return "", driver.ErrSkip
}
}
if argPos != len(args) {
return "", driver.ErrSkip
}
return string(buf), nil
}
func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
if len(args) != 0 {
if !mc.cfg.InterpolateParams {
return nil, driver.ErrSkip
}
// try to interpolate the parameters to save extra roundtrips for preparing and closing a statement
prepared, err := mc.interpolateParams(query, args)
if err != nil {
return nil, err
}
query = prepared
args = nil
}
mc.affectedRows = 0
mc.insertId = 0
err := mc.exec(query)
if err == nil {
return &mysqlResult{
affectedRows: int64(mc.affectedRows),
insertId: int64(mc.insertId),
}, err
}
return nil, err
}
// Internal function to execute commands
func (mc *mysqlConn) exec(query string) error {
// Send command
err := mc.writeCommandPacketStr(comQuery, query)
if err != nil {
return err
}
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err == nil && resLen > 0 {
if err = mc.readUntilEOF(); err != nil {
return err
}
err = mc.readUntilEOF()
}
return err
}
func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
if len(args) != 0 {
if !mc.cfg.InterpolateParams {
return nil, driver.ErrSkip
}
// try client-side prepare to reduce roundtrip
prepared, err := mc.interpolateParams(query, args)
if err != nil {
return nil, err
}
query = prepared
args = nil
}
// Send command
err := mc.writeCommandPacketStr(comQuery, query)
if err == nil {
// Read Result
var resLen int
resLen, err = mc.readResultSetHeaderPacket()
if err == nil {
rows := new(textRows)
rows.mc = mc
if resLen == 0 {
// no columns, no more data
return emptyRows{}, nil
}
// Columns
rows.columns, err = mc.readColumns(resLen)
return rows, err
}
}
return nil, err
}
// Gets the value of the given MySQL System Variable
// The returned byte slice is only valid until the next read
func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {
// Send command
if err := mc.writeCommandPacketStr(comQuery, "SELECT @@"+name); err != nil {
return nil, err
}
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err == nil {
rows := new(textRows)
rows.mc = mc
rows.columns = []mysqlField{{fieldType: fieldTypeVarChar}}
if resLen > 0 {
// Columns
if err := mc.readUntilEOF(); err != nil {
return nil, err
}
}
dest := make([]driver.Value, resLen)
if err = rows.readRow(dest); err == nil {
return dest[0].([]byte), mc.readUntilEOF()
}
}
return nil, err
}

163
vendor/github.com/go-sql-driver/mysql/const.go generated vendored Normal file
View File

@ -0,0 +1,163 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
const (
minProtocolVersion byte = 10
maxPacketSize = 1<<24 - 1
timeFormat = "2006-01-02 15:04:05.999999"
)
// MySQL constants documentation:
// http://dev.mysql.com/doc/internals/en/client-server-protocol.html
const (
iOK byte = 0x00
iLocalInFile byte = 0xfb
iEOF byte = 0xfe
iERR byte = 0xff
)
// https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags
type clientFlag uint32
const (
clientLongPassword clientFlag = 1 << iota
clientFoundRows
clientLongFlag
clientConnectWithDB
clientNoSchema
clientCompress
clientODBC
clientLocalFiles
clientIgnoreSpace
clientProtocol41
clientInteractive
clientSSL
clientIgnoreSIGPIPE
clientTransactions
clientReserved
clientSecureConn
clientMultiStatements
clientMultiResults
clientPSMultiResults
clientPluginAuth
clientConnectAttrs
clientPluginAuthLenEncClientData
clientCanHandleExpiredPasswords
clientSessionTrack
clientDeprecateEOF
)
const (
comQuit byte = iota + 1
comInitDB
comQuery
comFieldList
comCreateDB
comDropDB
comRefresh
comShutdown
comStatistics
comProcessInfo
comConnect
comProcessKill
comDebug
comPing
comTime
comDelayedInsert
comChangeUser
comBinlogDump
comTableDump
comConnectOut
comRegisterSlave
comStmtPrepare
comStmtExecute
comStmtSendLongData
comStmtClose
comStmtReset
comSetOption
comStmtFetch
)
// https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnType
const (
fieldTypeDecimal byte = iota
fieldTypeTiny
fieldTypeShort
fieldTypeLong
fieldTypeFloat
fieldTypeDouble
fieldTypeNULL
fieldTypeTimestamp
fieldTypeLongLong
fieldTypeInt24
fieldTypeDate
fieldTypeTime
fieldTypeDateTime
fieldTypeYear
fieldTypeNewDate
fieldTypeVarChar
fieldTypeBit
)
const (
fieldTypeJSON byte = iota + 0xf5
fieldTypeNewDecimal
fieldTypeEnum
fieldTypeSet
fieldTypeTinyBLOB
fieldTypeMediumBLOB
fieldTypeLongBLOB
fieldTypeBLOB
fieldTypeVarString
fieldTypeString
fieldTypeGeometry
)
type fieldFlag uint16
const (
flagNotNULL fieldFlag = 1 << iota
flagPriKey
flagUniqueKey
flagMultipleKey
flagBLOB
flagUnsigned
flagZeroFill
flagBinary
flagEnum
flagAutoIncrement
flagTimestamp
flagSet
flagUnknown1
flagUnknown2
flagUnknown3
flagUnknown4
)
// http://dev.mysql.com/doc/internals/en/status-flags.html
type statusFlag uint16
const (
statusInTrans statusFlag = 1 << iota
statusInAutocommit
statusReserved // Not in documentation
statusMoreResultsExists
statusNoGoodIndexUsed
statusNoIndexUsed
statusCursorExists
statusLastRowSent
statusDbDropped
statusNoBackslashEscapes
statusMetadataChanged
statusQueryWasSlow
statusPsOutParams
statusInTransReadonly
statusSessionStateChanged
)

183
vendor/github.com/go-sql-driver/mysql/driver.go generated vendored Normal file
View File

@ -0,0 +1,183 @@
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// Package mysql provides a MySQL driver for Go's database/sql package
//
// The driver should be used via the database/sql package:
//
// import "database/sql"
// import _ "github.com/go-sql-driver/mysql"
//
// db, err := sql.Open("mysql", "user:password@/dbname")
//
// See https://github.com/go-sql-driver/mysql#usage for details
package mysql
import (
"database/sql"
"database/sql/driver"
"net"
)
// MySQLDriver is exported to make the driver directly accessible.
// In general the driver is used via the database/sql package.
type MySQLDriver struct{}
// DialFunc is a function which can be used to establish the network connection.
// Custom dial functions must be registered with RegisterDial
type DialFunc func(addr string) (net.Conn, error)
var dials map[string]DialFunc
// RegisterDial registers a custom dial function. It can then be used by the
// network address mynet(addr), where mynet is the registered new network.
// addr is passed as a parameter to the dial function.
func RegisterDial(net string, dial DialFunc) {
if dials == nil {
dials = make(map[string]DialFunc)
}
dials[net] = dial
}
// Open new Connection.
// See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how
// the DSN string is formated
func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
var err error
// New mysqlConn
mc := &mysqlConn{
maxAllowedPacket: maxPacketSize,
maxWriteSize: maxPacketSize - 1,
}
mc.cfg, err = ParseDSN(dsn)
if err != nil {
return nil, err
}
mc.parseTime = mc.cfg.ParseTime
mc.strict = mc.cfg.Strict
// Connect to Server
if dial, ok := dials[mc.cfg.Net]; ok {
mc.netConn, err = dial(mc.cfg.Addr)
} else {
nd := net.Dialer{Timeout: mc.cfg.Timeout}
mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr)
}
if err != nil {
return nil, err
}
// Enable TCP Keepalives on TCP connections
if tc, ok := mc.netConn.(*net.TCPConn); ok {
if err := tc.SetKeepAlive(true); err != nil {
// Don't send COM_QUIT before handshake.
mc.netConn.Close()
mc.netConn = nil
return nil, err
}
}
mc.buf = newBuffer(mc.netConn)
// Set I/O timeouts
mc.buf.timeout = mc.cfg.ReadTimeout
mc.writeTimeout = mc.cfg.WriteTimeout
// Reading Handshake Initialization Packet
cipher, err := mc.readInitPacket()
if err != nil {
mc.cleanup()
return nil, err
}
// Send Client Authentication Packet
if err = mc.writeAuthPacket(cipher); err != nil {
mc.cleanup()
return nil, err
}
// Handle response to auth packet, switch methods if possible
if err = handleAuthResult(mc, cipher); err != nil {
// Authentication failed and MySQL has already closed the connection
// (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
// Do not send COM_QUIT, just cleanup and return the error.
mc.cleanup()
return nil, err
}
if mc.cfg.MaxAllowedPacket > 0 {
mc.maxAllowedPacket = mc.cfg.MaxAllowedPacket
} else {
// Get max allowed packet size
maxap, err := mc.getSystemVar("max_allowed_packet")
if err != nil {
mc.Close()
return nil, err
}
mc.maxAllowedPacket = stringToInt(maxap) - 1
}
if mc.maxAllowedPacket < maxPacketSize {
mc.maxWriteSize = mc.maxAllowedPacket
}
// Handle DSN Params
err = mc.handleParams()
if err != nil {
mc.Close()
return nil, err
}
return mc, nil
}
func handleAuthResult(mc *mysqlConn, oldCipher []byte) error {
// Read Result Packet
cipher, err := mc.readResultOK()
if err == nil {
return nil // auth successful
}
if mc.cfg == nil {
return err // auth failed and retry not possible
}
// Retry auth if configured to do so.
if mc.cfg.AllowOldPasswords && err == ErrOldPassword {
// Retry with old authentication method. Note: there are edge cases
// where this should work but doesn't; this is currently "wontfix":
// https://github.com/go-sql-driver/mysql/issues/184
// If CLIENT_PLUGIN_AUTH capability is not supported, no new cipher is
// sent and we have to keep using the cipher sent in the init packet.
if cipher == nil {
cipher = oldCipher
}
if err = mc.writeOldAuthPacket(cipher); err != nil {
return err
}
_, err = mc.readResultOK()
} else if mc.cfg.AllowCleartextPasswords && err == ErrCleartextPassword {
// Retry with clear text password for
// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
if err = mc.writeClearAuthPacket(); err != nil {
return err
}
_, err = mc.readResultOK()
} else if mc.cfg.AllowNativePasswords && err == ErrNativePassword {
if err = mc.writeNativeAuthPacket(cipher); err != nil {
return err
}
_, err = mc.readResultOK()
}
return err
}
func init() {
sql.Register("mysql", &MySQLDriver{})
}

548
vendor/github.com/go-sql-driver/mysql/dsn.go generated vendored Normal file
View File

@ -0,0 +1,548 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2016 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"bytes"
"crypto/tls"
"errors"
"fmt"
"net"
"net/url"
"strconv"
"strings"
"time"
)
var (
errInvalidDSNUnescaped = errors.New("invalid DSN: did you forget to escape a param value?")
errInvalidDSNAddr = errors.New("invalid DSN: network address not terminated (missing closing brace)")
errInvalidDSNNoSlash = errors.New("invalid DSN: missing the slash separating the database name")
errInvalidDSNUnsafeCollation = errors.New("invalid DSN: interpolateParams can not be used with unsafe collations")
)
// Config is a configuration parsed from a DSN string
type Config struct {
User string // Username
Passwd string // Password (requires User)
Net string // Network type
Addr string // Network address (requires Net)
DBName string // Database name
Params map[string]string // Connection parameters
Collation string // Connection collation
Loc *time.Location // Location for time.Time values
MaxAllowedPacket int // Max packet size allowed
TLSConfig string // TLS configuration name
tls *tls.Config // TLS configuration
Timeout time.Duration // Dial timeout
ReadTimeout time.Duration // I/O read timeout
WriteTimeout time.Duration // I/O write timeout
AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE
AllowCleartextPasswords bool // Allows the cleartext client side plugin
AllowNativePasswords bool // Allows the native password authentication method
AllowOldPasswords bool // Allows the old insecure password method
ClientFoundRows bool // Return number of matching rows instead of rows changed
ColumnsWithAlias bool // Prepend table alias to column names
InterpolateParams bool // Interpolate placeholders into query string
MultiStatements bool // Allow multiple statements in one query
ParseTime bool // Parse time values to time.Time
Strict bool // Return warnings as errors
}
// FormatDSN formats the given Config into a DSN string which can be passed to
// the driver.
func (cfg *Config) FormatDSN() string {
var buf bytes.Buffer
// [username[:password]@]
if len(cfg.User) > 0 {
buf.WriteString(cfg.User)
if len(cfg.Passwd) > 0 {
buf.WriteByte(':')
buf.WriteString(cfg.Passwd)
}
buf.WriteByte('@')
}
// [protocol[(address)]]
if len(cfg.Net) > 0 {
buf.WriteString(cfg.Net)
if len(cfg.Addr) > 0 {
buf.WriteByte('(')
buf.WriteString(cfg.Addr)
buf.WriteByte(')')
}
}
// /dbname
buf.WriteByte('/')
buf.WriteString(cfg.DBName)
// [?param1=value1&...&paramN=valueN]
hasParam := false
if cfg.AllowAllFiles {
hasParam = true
buf.WriteString("?allowAllFiles=true")
}
if cfg.AllowCleartextPasswords {
if hasParam {
buf.WriteString("&allowCleartextPasswords=true")
} else {
hasParam = true
buf.WriteString("?allowCleartextPasswords=true")
}
}
if cfg.AllowNativePasswords {
if hasParam {
buf.WriteString("&allowNativePasswords=true")
} else {
hasParam = true
buf.WriteString("?allowNativePasswords=true")
}
}
if cfg.AllowOldPasswords {
if hasParam {
buf.WriteString("&allowOldPasswords=true")
} else {
hasParam = true
buf.WriteString("?allowOldPasswords=true")
}
}
if cfg.ClientFoundRows {
if hasParam {
buf.WriteString("&clientFoundRows=true")
} else {
hasParam = true
buf.WriteString("?clientFoundRows=true")
}
}
if col := cfg.Collation; col != defaultCollation && len(col) > 0 {
if hasParam {
buf.WriteString("&collation=")
} else {
hasParam = true
buf.WriteString("?collation=")
}
buf.WriteString(col)
}
if cfg.ColumnsWithAlias {
if hasParam {
buf.WriteString("&columnsWithAlias=true")
} else {
hasParam = true
buf.WriteString("?columnsWithAlias=true")
}
}
if cfg.InterpolateParams {
if hasParam {
buf.WriteString("&interpolateParams=true")
} else {
hasParam = true
buf.WriteString("?interpolateParams=true")
}
}
if cfg.Loc != time.UTC && cfg.Loc != nil {
if hasParam {
buf.WriteString("&loc=")
} else {
hasParam = true
buf.WriteString("?loc=")
}
buf.WriteString(url.QueryEscape(cfg.Loc.String()))
}
if cfg.MultiStatements {
if hasParam {
buf.WriteString("&multiStatements=true")
} else {
hasParam = true
buf.WriteString("?multiStatements=true")
}
}
if cfg.ParseTime {
if hasParam {
buf.WriteString("&parseTime=true")
} else {
hasParam = true
buf.WriteString("?parseTime=true")
}
}
if cfg.ReadTimeout > 0 {
if hasParam {
buf.WriteString("&readTimeout=")
} else {
hasParam = true
buf.WriteString("?readTimeout=")
}
buf.WriteString(cfg.ReadTimeout.String())
}
if cfg.Strict {
if hasParam {
buf.WriteString("&strict=true")
} else {
hasParam = true
buf.WriteString("?strict=true")
}
}
if cfg.Timeout > 0 {
if hasParam {
buf.WriteString("&timeout=")
} else {
hasParam = true
buf.WriteString("?timeout=")
}
buf.WriteString(cfg.Timeout.String())
}
if len(cfg.TLSConfig) > 0 {
if hasParam {
buf.WriteString("&tls=")
} else {
hasParam = true
buf.WriteString("?tls=")
}
buf.WriteString(url.QueryEscape(cfg.TLSConfig))
}
if cfg.WriteTimeout > 0 {
if hasParam {
buf.WriteString("&writeTimeout=")
} else {
hasParam = true
buf.WriteString("?writeTimeout=")
}
buf.WriteString(cfg.WriteTimeout.String())
}
if cfg.MaxAllowedPacket > 0 {
if hasParam {
buf.WriteString("&maxAllowedPacket=")
} else {
hasParam = true
buf.WriteString("?maxAllowedPacket=")
}
buf.WriteString(strconv.Itoa(cfg.MaxAllowedPacket))
}
// other params
if cfg.Params != nil {
for param, value := range cfg.Params {
if hasParam {
buf.WriteByte('&')
} else {
hasParam = true
buf.WriteByte('?')
}
buf.WriteString(param)
buf.WriteByte('=')
buf.WriteString(url.QueryEscape(value))
}
}
return buf.String()
}
// ParseDSN parses the DSN string to a Config
func ParseDSN(dsn string) (cfg *Config, err error) {
// New config with some default values
cfg = &Config{
Loc: time.UTC,
Collation: defaultCollation,
}
// [user[:password]@][net[(addr)]]/dbname[?param1=value1&paramN=valueN]
// Find the last '/' (since the password or the net addr might contain a '/')
foundSlash := false
for i := len(dsn) - 1; i >= 0; i-- {
if dsn[i] == '/' {
foundSlash = true
var j, k int
// left part is empty if i <= 0
if i > 0 {
// [username[:password]@][protocol[(address)]]
// Find the last '@' in dsn[:i]
for j = i; j >= 0; j-- {
if dsn[j] == '@' {
// username[:password]
// Find the first ':' in dsn[:j]
for k = 0; k < j; k++ {
if dsn[k] == ':' {
cfg.Passwd = dsn[k+1 : j]
break
}
}
cfg.User = dsn[:k]
break
}
}
// [protocol[(address)]]
// Find the first '(' in dsn[j+1:i]
for k = j + 1; k < i; k++ {
if dsn[k] == '(' {
// dsn[i-1] must be == ')' if an address is specified
if dsn[i-1] != ')' {
if strings.ContainsRune(dsn[k+1:i], ')') {
return nil, errInvalidDSNUnescaped
}
return nil, errInvalidDSNAddr
}
cfg.Addr = dsn[k+1 : i-1]
break
}
}
cfg.Net = dsn[j+1 : k]
}
// dbname[?param1=value1&...&paramN=valueN]
// Find the first '?' in dsn[i+1:]
for j = i + 1; j < len(dsn); j++ {
if dsn[j] == '?' {
if err = parseDSNParams(cfg, dsn[j+1:]); err != nil {
return
}
break
}
}
cfg.DBName = dsn[i+1 : j]
break
}
}
if !foundSlash && len(dsn) > 0 {
return nil, errInvalidDSNNoSlash
}
if cfg.InterpolateParams && unsafeCollations[cfg.Collation] {
return nil, errInvalidDSNUnsafeCollation
}
// Set default network if empty
if cfg.Net == "" {
cfg.Net = "tcp"
}
// Set default address if empty
if cfg.Addr == "" {
switch cfg.Net {
case "tcp":
cfg.Addr = "127.0.0.1:3306"
case "unix":
cfg.Addr = "/tmp/mysql.sock"
default:
return nil, errors.New("default addr for network '" + cfg.Net + "' unknown")
}
}
return
}
// parseDSNParams parses the DSN "query string"
// Values must be url.QueryEscape'ed
func parseDSNParams(cfg *Config, params string) (err error) {
for _, v := range strings.Split(params, "&") {
param := strings.SplitN(v, "=", 2)
if len(param) != 2 {
continue
}
// cfg params
switch value := param[1]; param[0] {
// Disable INFILE whitelist / enable all files
case "allowAllFiles":
var isBool bool
cfg.AllowAllFiles, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Use cleartext authentication mode (MySQL 5.5.10+)
case "allowCleartextPasswords":
var isBool bool
cfg.AllowCleartextPasswords, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Use native password authentication
case "allowNativePasswords":
var isBool bool
cfg.AllowNativePasswords, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Use old authentication mode (pre MySQL 4.1)
case "allowOldPasswords":
var isBool bool
cfg.AllowOldPasswords, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Switch "rowsAffected" mode
case "clientFoundRows":
var isBool bool
cfg.ClientFoundRows, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Collation
case "collation":
cfg.Collation = value
break
case "columnsWithAlias":
var isBool bool
cfg.ColumnsWithAlias, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Compression
case "compress":
return errors.New("compression not implemented yet")
// Enable client side placeholder substitution
case "interpolateParams":
var isBool bool
cfg.InterpolateParams, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Time Location
case "loc":
if value, err = url.QueryUnescape(value); err != nil {
return
}
cfg.Loc, err = time.LoadLocation(value)
if err != nil {
return
}
// multiple statements in one query
case "multiStatements":
var isBool bool
cfg.MultiStatements, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// time.Time parsing
case "parseTime":
var isBool bool
cfg.ParseTime, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// I/O read Timeout
case "readTimeout":
cfg.ReadTimeout, err = time.ParseDuration(value)
if err != nil {
return
}
// Strict mode
case "strict":
var isBool bool
cfg.Strict, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Dial Timeout
case "timeout":
cfg.Timeout, err = time.ParseDuration(value)
if err != nil {
return
}
// TLS-Encryption
case "tls":
boolValue, isBool := readBool(value)
if isBool {
if boolValue {
cfg.TLSConfig = "true"
cfg.tls = &tls.Config{}
} else {
cfg.TLSConfig = "false"
}
} else if vl := strings.ToLower(value); vl == "skip-verify" {
cfg.TLSConfig = vl
cfg.tls = &tls.Config{InsecureSkipVerify: true}
} else {
name, err := url.QueryUnescape(value)
if err != nil {
return fmt.Errorf("invalid value for TLS config name: %v", err)
}
if tlsConfig, ok := tlsConfigRegister[name]; ok {
if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {
host, _, err := net.SplitHostPort(cfg.Addr)
if err == nil {
tlsConfig.ServerName = host
}
}
cfg.TLSConfig = name
cfg.tls = tlsConfig
} else {
return errors.New("invalid value / unknown config name: " + name)
}
}
// I/O write Timeout
case "writeTimeout":
cfg.WriteTimeout, err = time.ParseDuration(value)
if err != nil {
return
}
case "maxAllowedPacket":
cfg.MaxAllowedPacket, err = strconv.Atoi(value)
if err != nil {
return
}
default:
// lazy init
if cfg.Params == nil {
cfg.Params = make(map[string]string)
}
if cfg.Params[param[0]], err = url.QueryUnescape(value); err != nil {
return
}
}
}
return
}

132
vendor/github.com/go-sql-driver/mysql/errors.go generated vendored Normal file
View File

@ -0,0 +1,132 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"errors"
"fmt"
"io"
"log"
"os"
)
// Various errors the driver might return. Can change between driver versions.
var (
ErrInvalidConn = errors.New("invalid connection")
ErrMalformPkt = errors.New("malformed packet")
ErrNoTLS = errors.New("TLS requested but server does not support TLS")
ErrCleartextPassword = errors.New("this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN")
ErrNativePassword = errors.New("this user requires mysql native password authentication.")
ErrOldPassword = errors.New("this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords")
ErrUnknownPlugin = errors.New("this authentication plugin is not supported")
ErrOldProtocol = errors.New("MySQL server does not support required protocol 41+")
ErrPktSync = errors.New("commands out of sync. You can't run this command now")
ErrPktSyncMul = errors.New("commands out of sync. Did you run multiple statements at once?")
ErrPktTooLarge = errors.New("packet for query is too large. Try adjusting the 'max_allowed_packet' variable on the server")
ErrBusyBuffer = errors.New("busy buffer")
)
var errLog = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime|log.Lshortfile))
// Logger is used to log critical error messages.
type Logger interface {
Print(v ...interface{})
}
// SetLogger is used to set the logger for critical errors.
// The initial logger is os.Stderr.
func SetLogger(logger Logger) error {
if logger == nil {
return errors.New("logger is nil")
}
errLog = logger
return nil
}
// MySQLError is an error type which represents a single MySQL error
type MySQLError struct {
Number uint16
Message string
}
func (me *MySQLError) Error() string {
return fmt.Sprintf("Error %d: %s", me.Number, me.Message)
}
// MySQLWarnings is an error type which represents a group of one or more MySQL
// warnings
type MySQLWarnings []MySQLWarning
func (mws MySQLWarnings) Error() string {
var msg string
for i, warning := range mws {
if i > 0 {
msg += "\r\n"
}
msg += fmt.Sprintf(
"%s %s: %s",
warning.Level,
warning.Code,
warning.Message,
)
}
return msg
}
// MySQLWarning is an error type which represents a single MySQL warning.
// Warnings are returned in groups only. See MySQLWarnings
type MySQLWarning struct {
Level string
Code string
Message string
}
func (mc *mysqlConn) getWarnings() (err error) {
rows, err := mc.Query("SHOW WARNINGS", nil)
if err != nil {
return
}
var warnings = MySQLWarnings{}
var values = make([]driver.Value, 3)
for {
err = rows.Next(values)
switch err {
case nil:
warning := MySQLWarning{}
if raw, ok := values[0].([]byte); ok {
warning.Level = string(raw)
} else {
warning.Level = fmt.Sprintf("%s", values[0])
}
if raw, ok := values[1].([]byte); ok {
warning.Code = string(raw)
} else {
warning.Code = fmt.Sprintf("%s", values[1])
}
if raw, ok := values[2].([]byte); ok {
warning.Message = string(raw)
} else {
warning.Message = fmt.Sprintf("%s", values[0])
}
warnings = append(warnings, warning)
case io.EOF:
return warnings
default:
rows.Close()
return
}
}
}

182
vendor/github.com/go-sql-driver/mysql/infile.go generated vendored Normal file
View File

@ -0,0 +1,182 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"fmt"
"io"
"os"
"strings"
"sync"
)
var (
fileRegister map[string]bool
fileRegisterLock sync.RWMutex
readerRegister map[string]func() io.Reader
readerRegisterLock sync.RWMutex
)
// RegisterLocalFile adds the given file to the file whitelist,
// so that it can be used by "LOAD DATA LOCAL INFILE <filepath>".
// Alternatively you can allow the use of all local files with
// the DSN parameter 'allowAllFiles=true'
//
// filePath := "/home/gopher/data.csv"
// mysql.RegisterLocalFile(filePath)
// err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo")
// if err != nil {
// ...
//
func RegisterLocalFile(filePath string) {
fileRegisterLock.Lock()
// lazy map init
if fileRegister == nil {
fileRegister = make(map[string]bool)
}
fileRegister[strings.Trim(filePath, `"`)] = true
fileRegisterLock.Unlock()
}
// DeregisterLocalFile removes the given filepath from the whitelist.
func DeregisterLocalFile(filePath string) {
fileRegisterLock.Lock()
delete(fileRegister, strings.Trim(filePath, `"`))
fileRegisterLock.Unlock()
}
// RegisterReaderHandler registers a handler function which is used
// to receive a io.Reader.
// The Reader can be used by "LOAD DATA LOCAL INFILE Reader::<name>".
// If the handler returns a io.ReadCloser Close() is called when the
// request is finished.
//
// mysql.RegisterReaderHandler("data", func() io.Reader {
// var csvReader io.Reader // Some Reader that returns CSV data
// ... // Open Reader here
// return csvReader
// })
// err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo")
// if err != nil {
// ...
//
func RegisterReaderHandler(name string, handler func() io.Reader) {
readerRegisterLock.Lock()
// lazy map init
if readerRegister == nil {
readerRegister = make(map[string]func() io.Reader)
}
readerRegister[name] = handler
readerRegisterLock.Unlock()
}
// DeregisterReaderHandler removes the ReaderHandler function with
// the given name from the registry.
func DeregisterReaderHandler(name string) {
readerRegisterLock.Lock()
delete(readerRegister, name)
readerRegisterLock.Unlock()
}
func deferredClose(err *error, closer io.Closer) {
closeErr := closer.Close()
if *err == nil {
*err = closeErr
}
}
func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
var rdr io.Reader
var data []byte
packetSize := 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP
if mc.maxWriteSize < packetSize {
packetSize = mc.maxWriteSize
}
if idx := strings.Index(name, "Reader::"); idx == 0 || (idx > 0 && name[idx-1] == '/') { // io.Reader
// The server might return an an absolute path. See issue #355.
name = name[idx+8:]
readerRegisterLock.RLock()
handler, inMap := readerRegister[name]
readerRegisterLock.RUnlock()
if inMap {
rdr = handler()
if rdr != nil {
if cl, ok := rdr.(io.Closer); ok {
defer deferredClose(&err, cl)
}
} else {
err = fmt.Errorf("Reader '%s' is <nil>", name)
}
} else {
err = fmt.Errorf("Reader '%s' is not registered", name)
}
} else { // File
name = strings.Trim(name, `"`)
fileRegisterLock.RLock()
fr := fileRegister[name]
fileRegisterLock.RUnlock()
if mc.cfg.AllowAllFiles || fr {
var file *os.File
var fi os.FileInfo
if file, err = os.Open(name); err == nil {
defer deferredClose(&err, file)
// get file size
if fi, err = file.Stat(); err == nil {
rdr = file
if fileSize := int(fi.Size()); fileSize < packetSize {
packetSize = fileSize
}
}
}
} else {
err = fmt.Errorf("local file '%s' is not registered", name)
}
}
// send content packets
if err == nil {
data := make([]byte, 4+packetSize)
var n int
for err == nil {
n, err = rdr.Read(data[4:])
if n > 0 {
if ioErr := mc.writePacket(data[:4+n]); ioErr != nil {
return ioErr
}
}
}
if err == io.EOF {
err = nil
}
}
// send empty packet (termination)
if data == nil {
data = make([]byte, 4)
}
if ioErr := mc.writePacket(data[:4]); ioErr != nil {
return ioErr
}
// read OK packet
if err == nil {
_, err = mc.readResultOK()
return err
}
mc.readPacket()
return err
}

1287
vendor/github.com/go-sql-driver/mysql/packets.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

22
vendor/github.com/go-sql-driver/mysql/result.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
type mysqlResult struct {
affectedRows int64
insertId int64
}
func (res *mysqlResult) LastInsertId() (int64, error) {
return res.insertId, nil
}
func (res *mysqlResult) RowsAffected() (int64, error) {
return res.affectedRows, nil
}

112
vendor/github.com/go-sql-driver/mysql/rows.go generated vendored Normal file
View File

@ -0,0 +1,112 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"io"
)
type mysqlField struct {
tableName string
name string
flags fieldFlag
fieldType byte
decimals byte
}
type mysqlRows struct {
mc *mysqlConn
columns []mysqlField
}
type binaryRows struct {
mysqlRows
}
type textRows struct {
mysqlRows
}
type emptyRows struct{}
func (rows *mysqlRows) Columns() []string {
columns := make([]string, len(rows.columns))
if rows.mc != nil && rows.mc.cfg.ColumnsWithAlias {
for i := range columns {
if tableName := rows.columns[i].tableName; len(tableName) > 0 {
columns[i] = tableName + "." + rows.columns[i].name
} else {
columns[i] = rows.columns[i].name
}
}
} else {
for i := range columns {
columns[i] = rows.columns[i].name
}
}
return columns
}
func (rows *mysqlRows) Close() error {
mc := rows.mc
if mc == nil {
return nil
}
if mc.netConn == nil {
return ErrInvalidConn
}
// Remove unread packets from stream
err := mc.readUntilEOF()
if err == nil {
if err = mc.discardResults(); err != nil {
return err
}
}
rows.mc = nil
return err
}
func (rows *binaryRows) Next(dest []driver.Value) error {
if mc := rows.mc; mc != nil {
if mc.netConn == nil {
return ErrInvalidConn
}
// Fetch next row from stream
return rows.readRow(dest)
}
return io.EOF
}
func (rows *textRows) Next(dest []driver.Value) error {
if mc := rows.mc; mc != nil {
if mc.netConn == nil {
return ErrInvalidConn
}
// Fetch next row from stream
return rows.readRow(dest)
}
return io.EOF
}
func (rows emptyRows) Columns() []string {
return nil
}
func (rows emptyRows) Close() error {
return nil
}
func (rows emptyRows) Next(dest []driver.Value) error {
return io.EOF
}

153
vendor/github.com/go-sql-driver/mysql/statement.go generated vendored Normal file
View File

@ -0,0 +1,153 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"fmt"
"reflect"
"strconv"
)
type mysqlStmt struct {
mc *mysqlConn
id uint32
paramCount int
columns []mysqlField // cached from the first query
}
func (stmt *mysqlStmt) Close() error {
if stmt.mc == nil || stmt.mc.netConn == nil {
// driver.Stmt.Close can be called more than once, thus this function
// has to be idempotent.
// See also Issue #450 and golang/go#16019.
//errLog.Print(ErrInvalidConn)
return driver.ErrBadConn
}
err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
stmt.mc = nil
return err
}
func (stmt *mysqlStmt) NumInput() int {
return stmt.paramCount
}
func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
return converter{}
}
func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
if stmt.mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
// Send command
err := stmt.writeExecutePacket(args)
if err != nil {
return nil, err
}
mc := stmt.mc
mc.affectedRows = 0
mc.insertId = 0
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err == nil {
if resLen > 0 {
// Columns
err = mc.readUntilEOF()
if err != nil {
return nil, err
}
// Rows
err = mc.readUntilEOF()
}
if err == nil {
return &mysqlResult{
affectedRows: int64(mc.affectedRows),
insertId: int64(mc.insertId),
}, nil
}
}
return nil, err
}
func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
if stmt.mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
// Send command
err := stmt.writeExecutePacket(args)
if err != nil {
return nil, err
}
mc := stmt.mc
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err != nil {
return nil, err
}
rows := new(binaryRows)
if resLen > 0 {
rows.mc = mc
// Columns
// If not cached, read them and cache them
if stmt.columns == nil {
rows.columns, err = mc.readColumns(resLen)
stmt.columns = rows.columns
} else {
rows.columns = stmt.columns
err = mc.readUntilEOF()
}
}
return rows, err
}
type converter struct{}
func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
if driver.IsValue(v) {
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return c.ConvertValue(rv.Elem().Interface())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
return int64(rv.Uint()), nil
case reflect.Uint64:
u64 := rv.Uint()
if u64 >= 1<<63 {
return strconv.FormatUint(u64, 10), nil
}
return int64(u64), nil
case reflect.Float32, reflect.Float64:
return rv.Float(), nil
}
return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}

31
vendor/github.com/go-sql-driver/mysql/transaction.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
type mysqlTx struct {
mc *mysqlConn
}
func (tx *mysqlTx) Commit() (err error) {
if tx.mc == nil || tx.mc.netConn == nil {
return ErrInvalidConn
}
err = tx.mc.exec("COMMIT")
tx.mc = nil
return
}
func (tx *mysqlTx) Rollback() (err error) {
if tx.mc == nil || tx.mc.netConn == nil {
return ErrInvalidConn
}
err = tx.mc.exec("ROLLBACK")
tx.mc = nil
return
}

740
vendor/github.com/go-sql-driver/mysql/utils.go generated vendored Normal file
View File

@ -0,0 +1,740 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"crypto/sha1"
"crypto/tls"
"database/sql/driver"
"encoding/binary"
"fmt"
"io"
"strings"
"time"
)
var (
tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs
)
// RegisterTLSConfig registers a custom tls.Config to be used with sql.Open.
// Use the key as a value in the DSN where tls=value.
//
// rootCertPool := x509.NewCertPool()
// pem, err := ioutil.ReadFile("/path/ca-cert.pem")
// if err != nil {
// log.Fatal(err)
// }
// if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
// log.Fatal("Failed to append PEM.")
// }
// clientCert := make([]tls.Certificate, 0, 1)
// certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem")
// if err != nil {
// log.Fatal(err)
// }
// clientCert = append(clientCert, certs)
// mysql.RegisterTLSConfig("custom", &tls.Config{
// RootCAs: rootCertPool,
// Certificates: clientCert,
// })
// db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom")
//
func RegisterTLSConfig(key string, config *tls.Config) error {
if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" {
return fmt.Errorf("key '%s' is reserved", key)
}
if tlsConfigRegister == nil {
tlsConfigRegister = make(map[string]*tls.Config)
}
tlsConfigRegister[key] = config
return nil
}
// DeregisterTLSConfig removes the tls.Config associated with key.
func DeregisterTLSConfig(key string) {
if tlsConfigRegister != nil {
delete(tlsConfigRegister, key)
}
}
// Returns the bool value of the input.
// The 2nd return value indicates if the input was a valid bool value
func readBool(input string) (value bool, valid bool) {
switch input {
case "1", "true", "TRUE", "True":
return true, true
case "0", "false", "FALSE", "False":
return false, true
}
// Not a valid bool value
return
}
/******************************************************************************
* Authentication *
******************************************************************************/
// Encrypt password using 4.1+ method
func scramblePassword(scramble, password []byte) []byte {
if len(password) == 0 {
return nil
}
// stage1Hash = SHA1(password)
crypt := sha1.New()
crypt.Write(password)
stage1 := crypt.Sum(nil)
// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
// inner Hash
crypt.Reset()
crypt.Write(stage1)
hash := crypt.Sum(nil)
// outer Hash
crypt.Reset()
crypt.Write(scramble)
crypt.Write(hash)
scramble = crypt.Sum(nil)
// token = scrambleHash XOR stage1Hash
for i := range scramble {
scramble[i] ^= stage1[i]
}
return scramble
}
// Encrypt password using pre 4.1 (old password) method
// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
type myRnd struct {
seed1, seed2 uint32
}
const myRndMaxVal = 0x3FFFFFFF
// Pseudo random number generator
func newMyRnd(seed1, seed2 uint32) *myRnd {
return &myRnd{
seed1: seed1 % myRndMaxVal,
seed2: seed2 % myRndMaxVal,
}
}
// Tested to be equivalent to MariaDB's floating point variant
// http://play.golang.org/p/QHvhd4qved
// http://play.golang.org/p/RG0q4ElWDx
func (r *myRnd) NextByte() byte {
r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
return byte(uint64(r.seed1) * 31 / myRndMaxVal)
}
// Generate binary hash from byte string using insecure pre 4.1 method
func pwHash(password []byte) (result [2]uint32) {
var add uint32 = 7
var tmp uint32
result[0] = 1345345333
result[1] = 0x12345671
for _, c := range password {
// skip spaces and tabs in password
if c == ' ' || c == '\t' {
continue
}
tmp = uint32(c)
result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
result[1] += (result[1] << 8) ^ result[0]
add += tmp
}
// Remove sign bit (1<<31)-1)
result[0] &= 0x7FFFFFFF
result[1] &= 0x7FFFFFFF
return
}
// Encrypt password using insecure pre 4.1 method
func scrambleOldPassword(scramble, password []byte) []byte {
if len(password) == 0 {
return nil
}
scramble = scramble[:8]
hashPw := pwHash(password)
hashSc := pwHash(scramble)
r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
var out [8]byte
for i := range out {
out[i] = r.NextByte() + 64
}
mask := r.NextByte()
for i := range out {
out[i] ^= mask
}
return out[:]
}
/******************************************************************************
* Time related utils *
******************************************************************************/
// NullTime represents a time.Time that may be NULL.
// NullTime implements the Scanner interface so
// it can be used as a scan destination:
//
// var nt NullTime
// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt)
// ...
// if nt.Valid {
// // use nt.Time
// } else {
// // NULL value
// }
//
// This NullTime implementation is not driver-specific
type NullTime struct {
Time time.Time
Valid bool // Valid is true if Time is not NULL
}
// Scan implements the Scanner interface.
// The value type must be time.Time or string / []byte (formatted time-string),
// otherwise Scan fails.
func (nt *NullTime) Scan(value interface{}) (err error) {
if value == nil {
nt.Time, nt.Valid = time.Time{}, false
return
}
switch v := value.(type) {
case time.Time:
nt.Time, nt.Valid = v, true
return
case []byte:
nt.Time, err = parseDateTime(string(v), time.UTC)
nt.Valid = (err == nil)
return
case string:
nt.Time, err = parseDateTime(v, time.UTC)
nt.Valid = (err == nil)
return
}
nt.Valid = false
return fmt.Errorf("Can't convert %T to time.Time", value)
}
// Value implements the driver Valuer interface.
func (nt NullTime) Value() (driver.Value, error) {
if !nt.Valid {
return nil, nil
}
return nt.Time, nil
}
func parseDateTime(str string, loc *time.Location) (t time.Time, err error) {
base := "0000-00-00 00:00:00.0000000"
switch len(str) {
case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM"
if str == base[:len(str)] {
return
}
t, err = time.Parse(timeFormat[:len(str)], str)
default:
err = fmt.Errorf("invalid time string: %s", str)
return
}
// Adjust location
if err == nil && loc != time.UTC {
y, mo, d := t.Date()
h, mi, s := t.Clock()
t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil
}
return
}
func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Value, error) {
switch num {
case 0:
return time.Time{}, nil
case 4:
return time.Date(
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
0, 0, 0, 0,
loc,
), nil
case 7:
return time.Date(
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
int(data[4]), // hour
int(data[5]), // minutes
int(data[6]), // seconds
0,
loc,
), nil
case 11:
return time.Date(
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
int(data[4]), // hour
int(data[5]), // minutes
int(data[6]), // seconds
int(binary.LittleEndian.Uint32(data[7:11]))*1000, // nanoseconds
loc,
), nil
}
return nil, fmt.Errorf("invalid DATETIME packet length %d", num)
}
// zeroDateTime is used in formatBinaryDateTime to avoid an allocation
// if the DATE or DATETIME has the zero value.
// It must never be changed.
// The current behavior depends on database/sql copying the result.
var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value, error) {
// length expects the deterministic length of the zero value,
// negative time and 100+ hours are automatically added if needed
if len(src) == 0 {
if justTime {
return zeroDateTime[11 : 11+length], nil
}
return zeroDateTime[:length], nil
}
var dst []byte // return value
var pt, p1, p2, p3 byte // current digit pair
var zOffs byte // offset of value in zeroDateTime
if justTime {
switch length {
case
8, // time (can be up to 10 when negative and 100+ hours)
10, 11, 12, 13, 14, 15: // time with fractional seconds
default:
return nil, fmt.Errorf("illegal TIME length %d", length)
}
switch len(src) {
case 8, 12:
default:
return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
}
// +2 to enable negative time and 100+ hours
dst = make([]byte, 0, length+2)
if src[0] == 1 {
dst = append(dst, '-')
}
if src[1] != 0 {
hour := uint16(src[1])*24 + uint16(src[5])
pt = byte(hour / 100)
p1 = byte(hour - 100*uint16(pt))
dst = append(dst, digits01[pt])
} else {
p1 = src[5]
}
zOffs = 11
src = src[6:]
} else {
switch length {
case 10, 19, 21, 22, 23, 24, 25, 26:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s length %d", t, length)
}
switch len(src) {
case 4, 7, 11:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
}
dst = make([]byte, 0, length)
// start with the date
year := binary.LittleEndian.Uint16(src[:2])
pt = byte(year / 100)
p1 = byte(year - 100*uint16(pt))
p2, p3 = src[2], src[3]
dst = append(dst,
digits10[pt], digits01[pt],
digits10[p1], digits01[p1], '-',
digits10[p2], digits01[p2], '-',
digits10[p3], digits01[p3],
)
if length == 10 {
return dst, nil
}
if len(src) == 4 {
return append(dst, zeroDateTime[10:length]...), nil
}
dst = append(dst, ' ')
p1 = src[4] // hour
src = src[5:]
}
// p1 is 2-digit hour, src is after hour
p2, p3 = src[0], src[1]
dst = append(dst,
digits10[p1], digits01[p1], ':',
digits10[p2], digits01[p2], ':',
digits10[p3], digits01[p3],
)
if length <= byte(len(dst)) {
return dst, nil
}
src = src[2:]
if len(src) == 0 {
return append(dst, zeroDateTime[19:zOffs+length]...), nil
}
microsecs := binary.LittleEndian.Uint32(src[:4])
p1 = byte(microsecs / 10000)
microsecs -= 10000 * uint32(p1)
p2 = byte(microsecs / 100)
microsecs -= 100 * uint32(p2)
p3 = byte(microsecs)
switch decimals := zOffs + length - 20; decimals {
default:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3], digits01[p3],
), nil
case 1:
return append(dst, '.',
digits10[p1],
), nil
case 2:
return append(dst, '.',
digits10[p1], digits01[p1],
), nil
case 3:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2],
), nil
case 4:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
), nil
case 5:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3],
), nil
}
}
/******************************************************************************
* Convert from and to bytes *
******************************************************************************/
func uint64ToBytes(n uint64) []byte {
return []byte{
byte(n),
byte(n >> 8),
byte(n >> 16),
byte(n >> 24),
byte(n >> 32),
byte(n >> 40),
byte(n >> 48),
byte(n >> 56),
}
}
func uint64ToString(n uint64) []byte {
var a [20]byte
i := 20
// U+0030 = 0
// ...
// U+0039 = 9
var q uint64
for n >= 10 {
i--
q = n / 10
a[i] = uint8(n-q*10) + 0x30
n = q
}
i--
a[i] = uint8(n) + 0x30
return a[i:]
}
// treats string value as unsigned integer representation
func stringToInt(b []byte) int {
val := 0
for i := range b {
val *= 10
val += int(b[i] - 0x30)
}
return val
}
// returns the string read as a bytes slice, wheter the value is NULL,
// the number of bytes read and an error, in case the string is longer than
// the input slice
func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {
// Get length
num, isNull, n := readLengthEncodedInteger(b)
if num < 1 {
return b[n:n], isNull, n, nil
}
n += int(num)
// Check data length
if len(b) >= n {
return b[n-int(num) : n], false, n, nil
}
return nil, false, n, io.EOF
}
// returns the number of bytes skipped and an error, in case the string is
// longer than the input slice
func skipLengthEncodedString(b []byte) (int, error) {
// Get length
num, _, n := readLengthEncodedInteger(b)
if num < 1 {
return n, nil
}
n += int(num)
// Check data length
if len(b) >= n {
return n, nil
}
return n, io.EOF
}
// returns the number read, whether the value is NULL and the number of bytes read
func readLengthEncodedInteger(b []byte) (uint64, bool, int) {
// See issue #349
if len(b) == 0 {
return 0, true, 1
}
switch b[0] {
// 251: NULL
case 0xfb:
return 0, true, 1
// 252: value of following 2
case 0xfc:
return uint64(b[1]) | uint64(b[2])<<8, false, 3
// 253: value of following 3
case 0xfd:
return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16, false, 4
// 254: value of following 8
case 0xfe:
return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16 |
uint64(b[4])<<24 | uint64(b[5])<<32 | uint64(b[6])<<40 |
uint64(b[7])<<48 | uint64(b[8])<<56,
false, 9
}
// 0-250: value of first byte
return uint64(b[0]), false, 1
}
// encodes a uint64 value and appends it to the given bytes slice
func appendLengthEncodedInteger(b []byte, n uint64) []byte {
switch {
case n <= 250:
return append(b, byte(n))
case n <= 0xffff:
return append(b, 0xfc, byte(n), byte(n>>8))
case n <= 0xffffff:
return append(b, 0xfd, byte(n), byte(n>>8), byte(n>>16))
}
return append(b, 0xfe, byte(n), byte(n>>8), byte(n>>16), byte(n>>24),
byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
}
// reserveBuffer checks cap(buf) and expand buffer to len(buf) + appendSize.
// If cap(buf) is not enough, reallocate new buffer.
func reserveBuffer(buf []byte, appendSize int) []byte {
newSize := len(buf) + appendSize
if cap(buf) < newSize {
// Grow buffer exponentially
newBuf := make([]byte, len(buf)*2+appendSize)
copy(newBuf, buf)
buf = newBuf
}
return buf[:newSize]
}
// escapeBytesBackslash escapes []byte with backslashes (\)
// This escapes the contents of a string (provided as []byte) by adding backslashes before special
// characters, and turning others into specific escape sequences, such as
// turning newlines into \n and null bytes into \0.
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L823-L932
func escapeBytesBackslash(buf, v []byte) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for _, c := range v {
switch c {
case '\x00':
buf[pos] = '\\'
buf[pos+1] = '0'
pos += 2
case '\n':
buf[pos] = '\\'
buf[pos+1] = 'n'
pos += 2
case '\r':
buf[pos] = '\\'
buf[pos+1] = 'r'
pos += 2
case '\x1a':
buf[pos] = '\\'
buf[pos+1] = 'Z'
pos += 2
case '\'':
buf[pos] = '\\'
buf[pos+1] = '\''
pos += 2
case '"':
buf[pos] = '\\'
buf[pos+1] = '"'
pos += 2
case '\\':
buf[pos] = '\\'
buf[pos+1] = '\\'
pos += 2
default:
buf[pos] = c
pos++
}
}
return buf[:pos]
}
// escapeStringBackslash is similar to escapeBytesBackslash but for string.
func escapeStringBackslash(buf []byte, v string) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for i := 0; i < len(v); i++ {
c := v[i]
switch c {
case '\x00':
buf[pos] = '\\'
buf[pos+1] = '0'
pos += 2
case '\n':
buf[pos] = '\\'
buf[pos+1] = 'n'
pos += 2
case '\r':
buf[pos] = '\\'
buf[pos+1] = 'r'
pos += 2
case '\x1a':
buf[pos] = '\\'
buf[pos+1] = 'Z'
pos += 2
case '\'':
buf[pos] = '\\'
buf[pos+1] = '\''
pos += 2
case '"':
buf[pos] = '\\'
buf[pos+1] = '"'
pos += 2
case '\\':
buf[pos] = '\\'
buf[pos+1] = '\\'
pos += 2
default:
buf[pos] = c
pos++
}
}
return buf[:pos]
}
// escapeBytesQuotes escapes apostrophes in []byte by doubling them up.
// This escapes the contents of a string by doubling up any apostrophes that
// it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
// effect on the server.
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L963-L1038
func escapeBytesQuotes(buf, v []byte) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for _, c := range v {
if c == '\'' {
buf[pos] = '\''
buf[pos+1] = '\''
pos += 2
} else {
buf[pos] = c
pos++
}
}
return buf[:pos]
}
// escapeStringQuotes is similar to escapeBytesQuotes but for string.
func escapeStringQuotes(buf []byte, v string) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for i := 0; i < len(v); i++ {
c := v[i]
if c == '\'' {
buf[pos] = '\''
buf[pos+1] = '\''
pos += 2
} else {
buf[pos] = c
pos++
}
}
return buf[:pos]
}

27
vendor/github.com/go-xorm/builder/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2016 The Xorm Authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

175
vendor/github.com/go-xorm/builder/README.md generated vendored Normal file
View File

@ -0,0 +1,175 @@
# SQL builder
[![CircleCI](https://circleci.com/gh/go-xorm/builder/tree/master.svg?style=svg)](https://circleci.com/gh/go-xorm/builder/tree/master)
Package builder is a lightweight and fast SQL builder for Go and XORM.
Make sure you have installed Go 1.1+ and then:
go get github.com/go-xorm/builder
# Insert
```Go
sql, args, err := Insert(Eq{"c": 1, "d": 2}).Into("table1").ToSQL()
```
# Select
```Go
sql, args, err := Select("c, d").From("table1").Where(Eq{"a": 1}).ToSQL()
sql, args, err = Select("c, d").From("table1").LeftJoin("table2", Eq{"table1.id": 1}.And(Lt{"table2.id": 3})).
RightJoin("table3", "table2.id = table3.tid").Where(Eq{"a": 1}).ToSQL()
```
# Update
```Go
sql, args, err := Update(Eq{"a": 2}).From("table1").Where(Eq{"a": 1}).ToSQL()
```
# Delete
```Go
sql, args, err := Delete(Eq{"a": 1}).From("table1").ToSQL()
```
# Conditions
* `Eq` is a redefine of a map, you can give one or more conditions to `Eq`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Eq{"a":1})
// a=? [1]
sql, args, _ := ToSQL(Eq{"b":"c"}.And(Eq{"c": 0}))
// b=? AND c=? ["c", 0]
sql, args, _ := ToSQL(Eq{"b":"c", "c":0})
// b=? AND c=? ["c", 0]
sql, args, _ := ToSQL(Eq{"b":"c"}.Or(Eq{"b":"d"}))
// b=? OR b=? ["c", "d"]
sql, args, _ := ToSQL(Eq{"b": []string{"c", "d"}})
// b IN (?,?) ["c", "d"]
sql, args, _ := ToSQL(Eq{"b": 1, "c":[]int{2, 3}})
// b=? AND c IN (?,?) [1, 2, 3]
```
* `Neq` is the same to `Eq`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Neq{"a":1})
// a<>? [1]
sql, args, _ := ToSQL(Neq{"b":"c"}.And(Neq{"c": 0}))
// b<>? AND c<>? ["c", 0]
sql, args, _ := ToSQL(Neq{"b":"c", "c":0})
// b<>? AND c<>? ["c", 0]
sql, args, _ := ToSQL(Neq{"b":"c"}.Or(Neq{"b":"d"}))
// b<>? OR b<>? ["c", "d"]
sql, args, _ := ToSQL(Neq{"b": []string{"c", "d"}})
// b NOT IN (?,?) ["c", "d"]
sql, args, _ := ToSQL(Neq{"b": 1, "c":[]int{2, 3}})
// b<>? AND c NOT IN (?,?) [1, 2, 3]
```
* `Gt`, `Gte`, `Lt`, `Lte`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Gt{"a", 1}.And(Gte{"b", 2}))
// a>? AND b>=? [1, 2]
sql, args, _ := ToSQL(Lt{"a", 1}.Or(Lte{"b", 2}))
// a<? OR b<=? [1, 2]
```
* `Like`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Like{"a", "c"})
// a LIKE ? [%c%]
```
* `Expr` you can customerize your sql with `Expr`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Expr("a = ? ", 1))
// a = ? [1]
sql, args, _ := ToSQL(Eq{"a": Expr("select id from table where c = ?", 1)})
// a=(select id from table where c = ?) [1]
```
* `In` and `NotIn`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(In("a", 1, 2, 3))
// a IN (?,?,?) [1,2,3]
sql, args, _ := ToSQL(In("a", []int{1, 2, 3}))
// a IN (?,?,?) [1,2,3]
sql, args, _ := ToSQL(In("a", Expr("select id from b where c = ?", 1))))
// a IN (select id from b where c = ?) [1]
```
* `IsNull` and `NotNull`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(IsNull{"a"})
// a IS NULL []
sql, args, _ := ToSQL(NotNull{"b"})
// b IS NOT NULL []
```
* `And(conds ...Cond)`, And can connect one or more condtions via And
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(And(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2}))
// a=? AND b LIKE ? AND d<>? [1, %c%, 2]
```
* `Or(conds ...Cond)`, Or can connect one or more conditions via Or
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Or(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2}))
// a=? OR b LIKE ? OR d<>? [1, %c%, 2]
sql, args, _ := ToSQL(Or(Eq{"a":1}, And(Like{"b", "c"}, Neq{"d", 2})))
// a=? OR (b LIKE ? AND d<>?) [1, %c%, 2]
```
* `Between`
```Go
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Between{"a", 1, 2})
// a BETWEEN 1 AND 2
```
* Define yourself conditions
Since `Cond` is an interface.
```Go
type Cond interface {
WriteTo(Writer) error
And(...Cond) Cond
Or(...Cond) Cond
IsValid() bool
}
```
You can define yourself conditions and compose with other `Cond`.

190
vendor/github.com/go-xorm/builder/builder.go generated vendored Normal file
View File

@ -0,0 +1,190 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
type optype byte
const (
condType optype = iota // only conditions
selectType // select
insertType // insert
updateType // update
deleteType // delete
)
type join struct {
joinType string
joinTable string
joinCond Cond
}
// Builder describes a SQL statement
type Builder struct {
optype
tableName string
cond Cond
selects []string
joins []join
inserts Eq
updates []Eq
}
// Select creates a select Builder
func Select(cols ...string) *Builder {
builder := &Builder{cond: NewCond()}
return builder.Select(cols...)
}
// Insert creates an insert Builder
func Insert(eq Eq) *Builder {
builder := &Builder{cond: NewCond()}
return builder.Insert(eq)
}
// Update creates an update Builder
func Update(updates ...Eq) *Builder {
builder := &Builder{cond: NewCond()}
return builder.Update(updates...)
}
// Delete creates a delete Builder
func Delete(conds ...Cond) *Builder {
builder := &Builder{cond: NewCond()}
return builder.Delete(conds...)
}
// Where sets where SQL
func (b *Builder) Where(cond Cond) *Builder {
b.cond = b.cond.And(cond)
return b
}
// From sets the table name
func (b *Builder) From(tableName string) *Builder {
b.tableName = tableName
return b
}
// Into sets insert table name
func (b *Builder) Into(tableName string) *Builder {
b.tableName = tableName
return b
}
// Join sets join table and contions
func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder {
switch joinCond.(type) {
case Cond:
b.joins = append(b.joins, join{joinType, joinTable, joinCond.(Cond)})
case string:
b.joins = append(b.joins, join{joinType, joinTable, Expr(joinCond.(string))})
}
return b
}
// InnerJoin sets inner join
func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder {
return b.Join("INNER", joinTable, joinCond)
}
// LeftJoin sets left join SQL
func (b *Builder) LeftJoin(joinTable string, joinCond interface{}) *Builder {
return b.Join("LEFT", joinTable, joinCond)
}
// RightJoin sets right join SQL
func (b *Builder) RightJoin(joinTable string, joinCond interface{}) *Builder {
return b.Join("RIGHT", joinTable, joinCond)
}
// CrossJoin sets cross join SQL
func (b *Builder) CrossJoin(joinTable string, joinCond interface{}) *Builder {
return b.Join("CROSS", joinTable, joinCond)
}
// FullJoin sets full join SQL
func (b *Builder) FullJoin(joinTable string, joinCond interface{}) *Builder {
return b.Join("FULL", joinTable, joinCond)
}
// Select sets select SQL
func (b *Builder) Select(cols ...string) *Builder {
b.selects = cols
b.optype = selectType
return b
}
// And sets AND condition
func (b *Builder) And(cond Cond) *Builder {
b.cond = And(b.cond, cond)
return b
}
// Or sets OR condition
func (b *Builder) Or(cond Cond) *Builder {
b.cond = Or(b.cond, cond)
return b
}
// Insert sets insert SQL
func (b *Builder) Insert(eq Eq) *Builder {
b.inserts = eq
b.optype = insertType
return b
}
// Update sets update SQL
func (b *Builder) Update(updates ...Eq) *Builder {
b.updates = updates
b.optype = updateType
return b
}
// Delete sets delete SQL
func (b *Builder) Delete(conds ...Cond) *Builder {
b.cond = b.cond.And(conds...)
b.optype = deleteType
return b
}
// WriteTo implements Writer interface
func (b *Builder) WriteTo(w Writer) error {
switch b.optype {
case condType:
return b.cond.WriteTo(w)
case selectType:
return b.selectWriteTo(w)
case insertType:
return b.insertWriteTo(w)
case updateType:
return b.updateWriteTo(w)
case deleteType:
return b.deleteWriteTo(w)
}
return ErrNotSupportType
}
// ToSQL convert a builder to SQL and args
func (b *Builder) ToSQL() (string, []interface{}, error) {
w := NewWriter()
if err := b.WriteTo(w); err != nil {
return "", nil, err
}
return w.writer.String(), w.args, nil
}
// ToSQL convert a builder or condtions to SQL and args
func ToSQL(cond interface{}) (string, []interface{}, error) {
switch cond.(type) {
case Cond:
return condToSQL(cond.(Cond))
case *Builder:
return cond.(*Builder).ToSQL()
}
return "", nil, ErrNotSupportType
}

22
vendor/github.com/go-xorm/builder/builder_delete.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"errors"
"fmt"
)
func (b *Builder) deleteWriteTo(w Writer) error {
if len(b.tableName) <= 0 {
return errors.New("no table indicated")
}
if _, err := fmt.Fprintf(w, "DELETE FROM %s WHERE ", b.tableName); err != nil {
return err
}
return b.cond.WriteTo(w)
}

64
vendor/github.com/go-xorm/builder/builder_insert.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"bytes"
"errors"
"fmt"
)
func (b *Builder) insertWriteTo(w Writer) error {
if len(b.tableName) <= 0 {
return errors.New("no table indicated")
}
if len(b.inserts) <= 0 {
return errors.New("no column to be update")
}
if _, err := fmt.Fprintf(w, "INSERT INTO %s (", b.tableName); err != nil {
return err
}
var args = make([]interface{}, 0)
var bs []byte
var valBuffer = bytes.NewBuffer(bs)
var i = 0
for col, value := range b.inserts {
fmt.Fprint(w, col)
if e, ok := value.(expr); ok {
fmt.Fprint(valBuffer, e.sql)
args = append(args, e.args...)
} else {
fmt.Fprint(valBuffer, "?")
args = append(args, value)
}
if i != len(b.inserts)-1 {
if _, err := fmt.Fprint(w, ","); err != nil {
return err
}
if _, err := fmt.Fprint(valBuffer, ","); err != nil {
return err
}
}
i = i + 1
}
if _, err := fmt.Fprint(w, ") Values ("); err != nil {
return err
}
if _, err := w.Write(valBuffer.Bytes()); err != nil {
return err
}
if _, err := fmt.Fprint(w, ")"); err != nil {
return err
}
w.Append(args...)
return nil
}

53
vendor/github.com/go-xorm/builder/builder_select.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"errors"
"fmt"
)
func (b *Builder) selectWriteTo(w Writer) error {
if len(b.tableName) <= 0 {
return errors.New("no table indicated")
}
if _, err := fmt.Fprint(w, "SELECT "); err != nil {
return err
}
if len(b.selects) > 0 {
for i, s := range b.selects {
if _, err := fmt.Fprint(w, s); err != nil {
return err
}
if i != len(b.selects)-1 {
if _, err := fmt.Fprint(w, ","); err != nil {
return err
}
}
}
} else {
if _, err := fmt.Fprint(w, "*"); err != nil {
return err
}
}
if _, err := fmt.Fprintf(w, " FROM %s", b.tableName); err != nil {
return err
}
for _, v := range b.joins {
fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable)
if err := v.joinCond.WriteTo(w); err != nil {
return err
}
}
if _, err := fmt.Fprint(w, " WHERE "); err != nil {
return err
}
return b.cond.WriteTo(w)
}

41
vendor/github.com/go-xorm/builder/builder_update.go generated vendored Normal file
View File

@ -0,0 +1,41 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"errors"
"fmt"
)
func (b *Builder) updateWriteTo(w Writer) error {
if len(b.tableName) <= 0 {
return errors.New("no table indicated")
}
if len(b.updates) <= 0 {
return errors.New("no column to be update")
}
if _, err := fmt.Fprintf(w, "UPDATE %s SET ", b.tableName); err != nil {
return err
}
for i, s := range b.updates {
if err := s.opWriteTo(",", w); err != nil {
return err
}
if i != len(b.updates)-1 {
if _, err := fmt.Fprint(w, ","); err != nil {
return err
}
}
}
if _, err := fmt.Fprint(w, " WHERE "); err != nil {
return err
}
return b.cond.WriteTo(w)
}

12
vendor/github.com/go-xorm/builder/circle.yml generated vendored Normal file
View File

@ -0,0 +1,12 @@
dependencies:
override:
# './...' is a relative pattern which means all subdirectories
- go get -t -d -v ./...
- go build -v
- go get -u github.com/golang/lint/golint
test:
override:
# './...' is a relative pattern which means all subdirectories
- golint ./...
- go test -v -race

87
vendor/github.com/go-xorm/builder/cond.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"bytes"
"io"
)
// Writer defines the interface
type Writer interface {
io.Writer
Append(...interface{})
}
var _ Writer = NewWriter()
// BytesWriter implments Writer and save SQL in bytes.Buffer
type BytesWriter struct {
writer *bytes.Buffer
buffer []byte
args []interface{}
}
// NewWriter creates a new string writer
func NewWriter() *BytesWriter {
w := &BytesWriter{}
w.writer = bytes.NewBuffer(w.buffer)
return w
}
// Write writes data to Writer
func (s *BytesWriter) Write(buf []byte) (int, error) {
return s.writer.Write(buf)
}
// Append appends args to Writer
func (s *BytesWriter) Append(args ...interface{}) {
s.args = append(s.args, args...)
}
// Cond defines an interface
type Cond interface {
WriteTo(Writer) error
And(...Cond) Cond
Or(...Cond) Cond
IsValid() bool
}
type condEmpty struct{}
var _ Cond = condEmpty{}
// NewCond creates an empty condition
func NewCond() Cond {
return condEmpty{}
}
func (condEmpty) WriteTo(w Writer) error {
return nil
}
func (condEmpty) And(conds ...Cond) Cond {
return And(conds...)
}
func (condEmpty) Or(conds ...Cond) Cond {
return Or(conds...)
}
func (condEmpty) IsValid() bool {
return false
}
func condToSQL(cond Cond) (string, []interface{}, error) {
if cond == nil || !cond.IsValid() {
return "", nil, nil
}
w := NewWriter()
if err := cond.WriteTo(w); err != nil {
return "", nil, err
}
return w.writer.String(), w.args, nil
}

59
vendor/github.com/go-xorm/builder/cond_and.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
type condAnd []Cond
var _ Cond = condAnd{}
// And generates AND conditions
func And(conds ...Cond) Cond {
var result = make(condAnd, 0, len(conds))
for _, cond := range conds {
if cond == nil || !cond.IsValid() {
continue
}
result = append(result, cond)
}
return result
}
func (and condAnd) WriteTo(w Writer) error {
for i, cond := range and {
_, isOr := cond.(condOr)
if isOr {
fmt.Fprint(w, "(")
}
err := cond.WriteTo(w)
if err != nil {
return err
}
if isOr {
fmt.Fprint(w, ")")
}
if i != len(and)-1 {
fmt.Fprint(w, " AND ")
}
}
return nil
}
func (and condAnd) And(conds ...Cond) Cond {
return And(and, And(conds...))
}
func (and condAnd) Or(conds ...Cond) Cond {
return Or(and, Or(conds...))
}
func (and condAnd) IsValid() bool {
return len(and) > 0
}

40
vendor/github.com/go-xorm/builder/cond_between.go generated vendored Normal file
View File

@ -0,0 +1,40 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// Between implmentes between condition
type Between struct {
Col string
LessVal interface{}
MoreVal interface{}
}
var _ Cond = Between{}
// WriteTo write data to Writer
func (between Between) WriteTo(w Writer) error {
if _, err := fmt.Fprintf(w, "%s BETWEEN ? AND ?", between.Col); err != nil {
return err
}
w.Append(between.LessVal, between.MoreVal)
return nil
}
// And implments And with other conditions
func (between Between) And(conds ...Cond) Cond {
return And(between, And(conds...))
}
// Or implments Or with other conditions
func (between Between) Or(conds ...Cond) Cond {
return Or(between, Or(conds...))
}
// IsValid tests if the condition is valid
func (between Between) IsValid() bool {
return len(between.Col) > 0
}

154
vendor/github.com/go-xorm/builder/cond_compare.go generated vendored Normal file
View File

@ -0,0 +1,154 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// WriteMap writes conditions' SQL to Writer, op could be =, <>, >, <, <=, >= and etc.
func WriteMap(w Writer, data map[string]interface{}, op string) error {
var args = make([]interface{}, 0, len(data))
var i = 0
for k, v := range data {
switch v.(type) {
case expr:
if _, err := fmt.Fprintf(w, "%s%s(", k, op); err != nil {
return err
}
if err := v.(expr).WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
case *Builder:
if _, err := fmt.Fprintf(w, "%s%s(", k, op); err != nil {
return err
}
if err := v.(*Builder).WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
default:
if _, err := fmt.Fprintf(w, "%s%s?", k, op); err != nil {
return err
}
args = append(args, v)
}
if i != len(data)-1 {
if _, err := fmt.Fprint(w, " AND "); err != nil {
return err
}
}
i = i + 1
}
w.Append(args...)
return nil
}
// Lt defines < condition
type Lt map[string]interface{}
var _ Cond = Lt{}
// WriteTo write SQL to Writer
func (lt Lt) WriteTo(w Writer) error {
return WriteMap(w, lt, "<")
}
// And implements And with other conditions
func (lt Lt) And(conds ...Cond) Cond {
return condAnd{lt, And(conds...)}
}
// Or implements Or with other conditions
func (lt Lt) Or(conds ...Cond) Cond {
return condOr{lt, Or(conds...)}
}
// IsValid tests if this Eq is valid
func (lt Lt) IsValid() bool {
return len(lt) > 0
}
// Lte defines <= condition
type Lte map[string]interface{}
var _ Cond = Lte{}
// WriteTo write SQL to Writer
func (lte Lte) WriteTo(w Writer) error {
return WriteMap(w, lte, "<=")
}
// And implements And with other conditions
func (lte Lte) And(conds ...Cond) Cond {
return And(lte, And(conds...))
}
// Or implements Or with other conditions
func (lte Lte) Or(conds ...Cond) Cond {
return Or(lte, Or(conds...))
}
// IsValid tests if this Eq is valid
func (lte Lte) IsValid() bool {
return len(lte) > 0
}
// Gt defines > condition
type Gt map[string]interface{}
var _ Cond = Gt{}
// WriteTo write SQL to Writer
func (gt Gt) WriteTo(w Writer) error {
return WriteMap(w, gt, ">")
}
// And implements And with other conditions
func (gt Gt) And(conds ...Cond) Cond {
return And(gt, And(conds...))
}
// Or implements Or with other conditions
func (gt Gt) Or(conds ...Cond) Cond {
return Or(gt, Or(conds...))
}
// IsValid tests if this Eq is valid
func (gt Gt) IsValid() bool {
return len(gt) > 0
}
// Gte defines >= condition
type Gte map[string]interface{}
var _ Cond = Gte{}
// WriteTo write SQL to Writer
func (gte Gte) WriteTo(w Writer) error {
return WriteMap(w, gte, ">=")
}
// And implements And with other conditions
func (gte Gte) And(conds ...Cond) Cond {
return And(gte, And(conds...))
}
// Or implements Or with other conditions
func (gte Gte) Or(conds ...Cond) Cond {
return Or(gte, Or(conds...))
}
// IsValid tests if this Eq is valid
func (gte Gte) IsValid() bool {
return len(gte) > 0
}

96
vendor/github.com/go-xorm/builder/cond_eq.go generated vendored Normal file
View File

@ -0,0 +1,96 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// Incr implements a type used by Eq
type Incr int
// Decr implements a type used by Eq
type Decr int
// Eq defines equals conditions
type Eq map[string]interface{}
var _ Cond = Eq{}
func (eq Eq) opWriteTo(op string, w Writer) error {
var i = 0
for k, v := range eq {
switch v.(type) {
case []int, []int64, []string, []int32, []int16, []int8, []uint, []uint64, []uint32, []uint16, []interface{}:
if err := In(k, v).WriteTo(w); err != nil {
return err
}
case expr:
if _, err := fmt.Fprintf(w, "%s=(", k); err != nil {
return err
}
if err := v.(expr).WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
case *Builder:
if _, err := fmt.Fprintf(w, "%s=(", k); err != nil {
return err
}
if err := v.(*Builder).WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
case Incr:
if _, err := fmt.Fprintf(w, "%s=%s+?", k, k); err != nil {
return err
}
w.Append(int(v.(Incr)))
case Decr:
if _, err := fmt.Fprintf(w, "%s=%s-?", k, k); err != nil {
return err
}
w.Append(int(v.(Decr)))
default:
if _, err := fmt.Fprintf(w, "%s=?", k); err != nil {
return err
}
w.Append(v)
}
if i != len(eq)-1 {
if _, err := fmt.Fprint(w, op); err != nil {
return err
}
}
i = i + 1
}
return nil
}
// WriteTo writes SQL to Writer
func (eq Eq) WriteTo(w Writer) error {
return eq.opWriteTo(" AND ", w)
}
// And implements And with other conditions
func (eq Eq) And(conds ...Cond) Cond {
return And(eq, And(conds...))
}
// Or implements Or with other conditions
func (eq Eq) Or(conds ...Cond) Cond {
return Or(eq, Or(conds...))
}
// IsValid tests if this Eq is valid
func (eq Eq) IsValid() bool {
return len(eq) > 0
}

39
vendor/github.com/go-xorm/builder/cond_expr.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
type expr struct {
sql string
args []interface{}
}
var _ Cond = expr{}
// Expr generate customerize SQL
func Expr(sql string, args ...interface{}) Cond {
return expr{sql, args}
}
func (expr expr) WriteTo(w Writer) error {
if _, err := fmt.Fprint(w, expr.sql); err != nil {
return err
}
w.Append(expr.args...)
return nil
}
func (expr expr) And(conds ...Cond) Cond {
return And(expr, And(conds...))
}
func (expr expr) Or(conds ...Cond) Cond {
return Or(expr, Or(conds...))
}
func (expr expr) IsValid() bool {
return len(expr.sql) > 0
}

233
vendor/github.com/go-xorm/builder/cond_in.go generated vendored Normal file
View File

@ -0,0 +1,233 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"fmt"
"reflect"
"strings"
)
type condIn struct {
col string
vals []interface{}
}
var _ Cond = condIn{}
// In generates IN condition
func In(col string, values ...interface{}) Cond {
return condIn{col, values}
}
func (condIn condIn) WriteTo(w Writer) error {
if len(condIn.vals) <= 0 {
return ErrNoInConditions
}
switch condIn.vals[0].(type) {
case []int8:
vals := condIn.vals[0].([]int8)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int16:
vals := condIn.vals[0].([]int16)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int:
vals := condIn.vals[0].([]int)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int32:
vals := condIn.vals[0].([]int32)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int64:
vals := condIn.vals[0].([]int64)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint8:
vals := condIn.vals[0].([]uint8)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint16:
vals := condIn.vals[0].([]uint16)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint:
vals := condIn.vals[0].([]uint)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint32:
vals := condIn.vals[0].([]uint32)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint64:
vals := condIn.vals[0].([]uint64)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []string:
vals := condIn.vals[0].([]string)
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []interface{}:
vals := condIn.vals[0].([]interface{})
if len(vals) <= 0 {
return ErrNoInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
w.Append(vals...)
case expr:
val := condIn.vals[0].(expr)
if _, err := fmt.Fprintf(w, "%s IN (", condIn.col); err != nil {
return err
}
if err := val.WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
case *Builder:
bd := condIn.vals[0].(*Builder)
if _, err := fmt.Fprintf(w, "%s IN (", condIn.col); err != nil {
return err
}
if err := bd.WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
default:
if len(condIn.vals) <= 0 {
return ErrNoInConditions
}
v := reflect.ValueOf(condIn.vals[0])
if v.Kind() == reflect.Slice {
l := v.Len()
questionMark := strings.Repeat("?,", l)
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for i := 0; i < l; i++ {
w.Append(v.Index(i).Interface())
}
} else {
questionMark := strings.Repeat("?,", len(condIn.vals))
if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
w.Append(condIn.vals...)
}
}
return nil
}
func (condIn condIn) And(conds ...Cond) Cond {
return And(condIn, And(conds...))
}
func (condIn condIn) Or(conds ...Cond) Cond {
return Or(condIn, Or(conds...))
}
func (condIn condIn) IsValid() bool {
return len(condIn.col) > 0 && len(condIn.vals) > 0
}

36
vendor/github.com/go-xorm/builder/cond_like.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// Like defines like condition
type Like [2]string
var _ Cond = Like{"", ""}
// WriteTo write SQL to Writer
func (like Like) WriteTo(w Writer) error {
if _, err := fmt.Fprintf(w, "%s LIKE ?", like[0]); err != nil {
return err
}
w.Append("%" + like[1] + "%")
return nil
}
// And implements And with other conditions
func (like Like) And(conds ...Cond) Cond {
return And(like, And(conds...))
}
// Or implements Or with other conditions
func (like Like) Or(conds ...Cond) Cond {
return Or(like, Or(conds...))
}
// IsValid tests if this condition is valid
func (like Like) IsValid() bool {
return len(like[0]) > 0 && len(like[1]) > 0
}

78
vendor/github.com/go-xorm/builder/cond_neq.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// Neq defines not equal conditions
type Neq map[string]interface{}
var _ Cond = Neq{}
// WriteTo writes SQL to Writer
func (neq Neq) WriteTo(w Writer) error {
var args = make([]interface{}, 0, len(neq))
var i = 0
for k, v := range neq {
switch v.(type) {
case []int, []int64, []string, []int32, []int16, []int8:
if err := NotIn(k, v).WriteTo(w); err != nil {
return err
}
case expr:
if _, err := fmt.Fprintf(w, "%s<>(", k); err != nil {
return err
}
if err := v.(expr).WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
case *Builder:
if _, err := fmt.Fprintf(w, "%s<>(", k); err != nil {
return err
}
if err := v.(*Builder).WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
default:
if _, err := fmt.Fprintf(w, "%s<>?", k); err != nil {
return err
}
args = append(args, v)
}
if i != len(neq)-1 {
if _, err := fmt.Fprint(w, " AND "); err != nil {
return err
}
}
i = i + 1
}
w.Append(args...)
return nil
}
// And implements And with other conditions
func (neq Neq) And(conds ...Cond) Cond {
return And(neq, And(conds...))
}
// Or implements Or with other conditions
func (neq Neq) Or(conds ...Cond) Cond {
return Or(neq, Or(conds...))
}
// IsValid tests if this condition is valid
func (neq Neq) IsValid() bool {
return len(neq) > 0
}

53
vendor/github.com/go-xorm/builder/cond_not.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// Not defines NOT condition
type Not [1]Cond
var _ Cond = Not{}
// WriteTo writes SQL to Writer
func (not Not) WriteTo(w Writer) error {
if _, err := fmt.Fprint(w, "NOT "); err != nil {
return err
}
switch not[0].(type) {
case condAnd, condOr:
if _, err := fmt.Fprint(w, "("); err != nil {
return err
}
}
if err := not[0].WriteTo(w); err != nil {
return err
}
switch not[0].(type) {
case condAnd, condOr:
if _, err := fmt.Fprint(w, ")"); err != nil {
return err
}
}
return nil
}
// And implements And with other conditions
func (not Not) And(conds ...Cond) Cond {
return And(not, And(conds...))
}
// Or implements Or with other conditions
func (not Not) Or(conds ...Cond) Cond {
return Or(not, Or(conds...))
}
// IsValid tests if this condition is valid
func (not Not) IsValid() bool {
return not[0] != nil && not[0].IsValid()
}

211
vendor/github.com/go-xorm/builder/cond_notin.go generated vendored Normal file
View File

@ -0,0 +1,211 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"fmt"
"strings"
)
type condNotIn condIn
var _ Cond = condNotIn{}
// NotIn generate NOT IN condition
func NotIn(col string, values ...interface{}) Cond {
return condNotIn{col, values}
}
func (condNotIn condNotIn) WriteTo(w Writer) error {
if len(condNotIn.vals) <= 0 {
return ErrNoNotInConditions
}
switch condNotIn.vals[0].(type) {
case []int8:
vals := condNotIn.vals[0].([]int8)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int16:
vals := condNotIn.vals[0].([]int16)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int:
vals := condNotIn.vals[0].([]int)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int32:
vals := condNotIn.vals[0].([]int32)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []int64:
vals := condNotIn.vals[0].([]int64)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint8:
vals := condNotIn.vals[0].([]uint8)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint16:
vals := condNotIn.vals[0].([]uint16)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint:
vals := condNotIn.vals[0].([]uint)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint32:
vals := condNotIn.vals[0].([]uint32)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []uint64:
vals := condNotIn.vals[0].([]uint64)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []string:
vals := condNotIn.vals[0].([]string)
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
for _, val := range vals {
w.Append(val)
}
case []interface{}:
vals := condNotIn.vals[0].([]interface{})
if len(vals) <= 0 {
return ErrNoNotInConditions
}
questionMark := strings.Repeat("?,", len(vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
w.Append(vals...)
case expr:
val := condNotIn.vals[0].(expr)
if _, err := fmt.Fprintf(w, "%s NOT IN (", condNotIn.col); err != nil {
return err
}
if err := val.WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
case *Builder:
val := condNotIn.vals[0].(*Builder)
if _, err := fmt.Fprintf(w, "%s NOT IN (", condNotIn.col); err != nil {
return err
}
if err := val.WriteTo(w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, ")"); err != nil {
return err
}
default:
questionMark := strings.Repeat("?,", len(condNotIn.vals))
if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil {
return err
}
w.Append(condNotIn.vals...)
}
return nil
}
func (condNotIn condNotIn) And(conds ...Cond) Cond {
return And(condNotIn, And(conds...))
}
func (condNotIn condNotIn) Or(conds ...Cond) Cond {
return Or(condNotIn, Or(conds...))
}
func (condNotIn condNotIn) IsValid() bool {
return len(condNotIn.col) > 0 && len(condNotIn.vals) > 0
}

59
vendor/github.com/go-xorm/builder/cond_null.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// IsNull defines IS NULL condition
type IsNull [1]string
var _ Cond = IsNull{""}
// WriteTo write SQL to Writer
func (isNull IsNull) WriteTo(w Writer) error {
_, err := fmt.Fprintf(w, "%s IS NULL", isNull[0])
return err
}
// And implements And with other conditions
func (isNull IsNull) And(conds ...Cond) Cond {
return And(isNull, And(conds...))
}
// Or implements Or with other conditions
func (isNull IsNull) Or(conds ...Cond) Cond {
return Or(isNull, Or(conds...))
}
// IsValid tests if this condition is valid
func (isNull IsNull) IsValid() bool {
return len(isNull[0]) > 0
}
// NotNull defines NOT NULL condition
type NotNull [1]string
var _ Cond = NotNull{""}
// WriteTo write SQL to Writer
func (notNull NotNull) WriteTo(w Writer) error {
_, err := fmt.Fprintf(w, "%s IS NOT NULL", notNull[0])
return err
}
// And implements And with other conditions
func (notNull NotNull) And(conds ...Cond) Cond {
return And(notNull, And(conds...))
}
// Or implements Or with other conditions
func (notNull NotNull) Or(conds ...Cond) Cond {
return Or(notNull, Or(conds...))
}
// IsValid tests if this condition is valid
func (notNull NotNull) IsValid() bool {
return len(notNull[0]) > 0
}

67
vendor/github.com/go-xorm/builder/cond_or.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
type condOr []Cond
var _ Cond = condOr{}
// Or sets OR conditions
func Or(conds ...Cond) Cond {
var result = make(condOr, 0, len(conds))
for _, cond := range conds {
if cond == nil || !cond.IsValid() {
continue
}
result = append(result, cond)
}
return result
}
// WriteTo implments Cond
func (o condOr) WriteTo(w Writer) error {
for i, cond := range o {
var needQuote bool
switch cond.(type) {
case condAnd:
needQuote = true
case Eq:
needQuote = (len(cond.(Eq)) > 1)
}
if needQuote {
fmt.Fprint(w, "(")
}
err := cond.WriteTo(w)
if err != nil {
return err
}
if needQuote {
fmt.Fprint(w, ")")
}
if i != len(o)-1 {
fmt.Fprint(w, " OR ")
}
}
return nil
}
func (o condOr) And(conds ...Cond) Cond {
return And(o, And(conds...))
}
func (o condOr) Or(conds ...Cond) Cond {
return Or(o, Or(conds...))
}
func (o condOr) IsValid() bool {
return len(o) > 0
}

120
vendor/github.com/go-xorm/builder/doc.go generated vendored Normal file
View File

@ -0,0 +1,120 @@
// Copyright 2016 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
/*
Package builder is a simple and powerful sql builder for Go.
Make sure you have installed Go 1.1+ and then:
go get github.com/go-xorm/builder
WARNNING: Currently, only query conditions are supported. Below is the supported conditions.
1. Eq is a redefine of a map, you can give one or more conditions to Eq
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Eq{"a":1})
// a=? [1]
sql, args, _ := ToSQL(Eq{"b":"c"}.And(Eq{"c": 0}))
// b=? AND c=? ["c", 0]
sql, args, _ := ToSQL(Eq{"b":"c", "c":0})
// b=? AND c=? ["c", 0]
sql, args, _ := ToSQL(Eq{"b":"c"}.Or(Eq{"b":"d"}))
// b=? OR b=? ["c", "d"]
sql, args, _ := ToSQL(Eq{"b": []string{"c", "d"}})
// b IN (?,?) ["c", "d"]
sql, args, _ := ToSQL(Eq{"b": 1, "c":[]int{2, 3}})
// b=? AND c IN (?,?) [1, 2, 3]
2. Neq is the same to Eq
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Neq{"a":1})
// a<>? [1]
sql, args, _ := ToSQL(Neq{"b":"c"}.And(Neq{"c": 0}))
// b<>? AND c<>? ["c", 0]
sql, args, _ := ToSQL(Neq{"b":"c", "c":0})
// b<>? AND c<>? ["c", 0]
sql, args, _ := ToSQL(Neq{"b":"c"}.Or(Neq{"b":"d"}))
// b<>? OR b<>? ["c", "d"]
sql, args, _ := ToSQL(Neq{"b": []string{"c", "d"}})
// b NOT IN (?,?) ["c", "d"]
sql, args, _ := ToSQL(Neq{"b": 1, "c":[]int{2, 3}})
// b<>? AND c NOT IN (?,?) [1, 2, 3]
3. Gt, Gte, Lt, Lte
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Gt{"a", 1}.And(Gte{"b", 2}))
// a>? AND b>=? [1, 2]
sql, args, _ := ToSQL(Lt{"a", 1}.Or(Lte{"b", 2}))
// a<? OR b<=? [1, 2]
4. Like
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Like{"a", "c"})
// a LIKE ? [%c%]
5. Expr you can customerize your sql with Expr
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Expr("a = ? ", 1))
// a = ? [1]
sql, args, _ := ToSQL(Eq{"a": Expr("select id from table where c = ?", 1)})
// a=(select id from table where c = ?) [1]
6. In and NotIn
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(In("a", 1, 2, 3))
// a IN (?,?,?) [1,2,3]
sql, args, _ := ToSQL(In("a", []int{1, 2, 3}))
// a IN (?,?,?) [1,2,3]
sql, args, _ := ToSQL(In("a", Expr("select id from b where c = ?", 1))))
// a IN (select id from b where c = ?) [1]
7. IsNull and NotNull
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(IsNull{"a"})
// a IS NULL []
sql, args, _ := ToSQL(NotNull{"b"})
// b IS NOT NULL []
8. And(conds ...Cond), And can connect one or more condtions via AND
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(And(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2}))
// a=? AND b LIKE ? AND d<>? [1, %c%, 2]
9. Or(conds ...Cond), Or can connect one or more conditions via Or
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Or(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2}))
// a=? OR b LIKE ? OR d<>? [1, %c%, 2]
sql, args, _ := ToSQL(Or(Eq{"a":1}, And(Like{"b", "c"}, Neq{"d", 2})))
// a=? OR (b LIKE ? AND d<>?) [1, %c%, 2]
10. Between
import . "github.com/go-xorm/builder"
sql, args, _ := ToSQL(Between("a", 1, 2))
// a BETWEEN 1 AND 2
11. define yourself conditions
Since Cond is a interface, you can define yourself conditions and compare with them
*/
package builder

16
vendor/github.com/go-xorm/builder/error.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "errors"
var (
// ErrNotSupportType not supported SQL type error
ErrNotSupportType = errors.New("not supported SQL type")
// ErrNoNotInConditions no NOT IN params error
ErrNoNotInConditions = errors.New("No NOT IN conditions")
// ErrNoInConditions no IN params error
ErrNoInConditions = errors.New("No IN conditions")
)

27
vendor/github.com/go-xorm/core/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2013 - 2015 Lunny Xiao <xiaolunwen@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

116
vendor/github.com/go-xorm/core/README.md generated vendored Normal file
View File

@ -0,0 +1,116 @@
Core is a lightweight wrapper of sql.DB.
[![CircleCI](https://circleci.com/gh/go-xorm/core/tree/master.svg?style=svg)](https://circleci.com/gh/go-xorm/core/tree/master)
# Open
```Go
db, _ := core.Open(db, connstr)
```
# SetMapper
```Go
db.SetMapper(SameMapper())
```
## Scan usage
### Scan
```Go
rows, _ := db.Query()
for rows.Next() {
rows.Scan()
}
```
### ScanMap
```Go
rows, _ := db.Query()
for rows.Next() {
rows.ScanMap()
```
### ScanSlice
You can use `[]string`, `[][]byte`, `[]interface{}`, `[]*string`, `[]sql.NullString` to ScanSclice. Notice, slice's length should be equal or less than select columns.
```Go
rows, _ := db.Query()
cols, _ := rows.Columns()
for rows.Next() {
var s = make([]string, len(cols))
rows.ScanSlice(&s)
}
```
```Go
rows, _ := db.Query()
cols, _ := rows.Columns()
for rows.Next() {
var s = make([]*string, len(cols))
rows.ScanSlice(&s)
}
```
### ScanStruct
```Go
rows, _ := db.Query()
for rows.Next() {
rows.ScanStructByName()
rows.ScanStructByIndex()
}
```
## Query usage
```Go
rows, err := db.Query("select * from table where name = ?", name)
user = User{
Name:"lunny",
}
rows, err := db.QueryStruct("select * from table where name = ?Name",
&user)
var user = map[string]interface{}{
"name": "lunny",
}
rows, err = db.QueryMap("select * from table where name = ?name",
&user)
```
## QueryRow usage
```Go
row := db.QueryRow("select * from table where name = ?", name)
user = User{
Name:"lunny",
}
row := db.QueryRowStruct("select * from table where name = ?Name",
&user)
var user = map[string]interface{}{
"name": "lunny",
}
row = db.QueryRowMap("select * from table where name = ?name",
&user)
```
## Exec usage
```Go
db.Exec("insert into user (`name`, title, age, alias, nick_name,created) values (?,?,?,?,?,?)", name, title, age, alias...)
user = User{
Name:"lunny",
Title:"test",
Age: 18,
}
result, err = db.ExecStruct("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)",
&user)
var user = map[string]interface{}{
"Name": "lunny",
"Title": "test",
"Age": 18,
}
result, err = db.ExecMap("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)",
&user)
```

1
vendor/github.com/go-xorm/core/benchmark.sh generated vendored Normal file
View File

@ -0,0 +1 @@
go test -v -bench=. -run=XXX

87
vendor/github.com/go-xorm/core/cache.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
package core
import (
"errors"
"fmt"
"time"
"bytes"
"encoding/gob"
)
const (
// default cache expired time
CacheExpired = 60 * time.Minute
// not use now
CacheMaxMemory = 256
// evey ten minutes to clear all expired nodes
CacheGcInterval = 10 * time.Minute
// each time when gc to removed max nodes
CacheGcMaxRemoved = 20
)
var (
ErrCacheMiss = errors.New("xorm/cache: key not found.")
ErrNotStored = errors.New("xorm/cache: not stored.")
)
// CacheStore is a interface to store cache
type CacheStore interface {
// key is primary key or composite primary key
// value is struct's pointer
// key format : <tablename>-p-<pk1>-<pk2>...
Put(key string, value interface{}) error
Get(key string) (interface{}, error)
Del(key string) error
}
// Cacher is an interface to provide cache
// id format : u-<pk1>-<pk2>...
type Cacher interface {
GetIds(tableName, sql string) interface{}
GetBean(tableName string, id string) interface{}
PutIds(tableName, sql string, ids interface{})
PutBean(tableName string, id string, obj interface{})
DelIds(tableName, sql string)
DelBean(tableName string, id string)
ClearIds(tableName string)
ClearBeans(tableName string)
}
func encodeIds(ids []PK) (string, error) {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
err := enc.Encode(ids)
return buf.String(), err
}
func decodeIds(s string) ([]PK, error) {
pks := make([]PK, 0)
dec := gob.NewDecoder(bytes.NewBufferString(s))
err := dec.Decode(&pks)
return pks, err
}
func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]PK, error) {
bytes := m.GetIds(tableName, GenSqlKey(sql, args))
if bytes == nil {
return nil, errors.New("Not Exist")
}
return decodeIds(bytes.(string))
}
func PutCacheSql(m Cacher, ids []PK, tableName, sql string, args interface{}) error {
bytes, err := encodeIds(ids)
if err != nil {
return err
}
m.PutIds(tableName, GenSqlKey(sql, args), bytes)
return nil
}
func GenSqlKey(sql string, args interface{}) string {
return fmt.Sprintf("%v-%v", sql, args)
}

14
vendor/github.com/go-xorm/core/circle.yml generated vendored Normal file
View File

@ -0,0 +1,14 @@
dependencies:
override:
# './...' is a relative pattern which means all subdirectories
- go get -t -d -v ./...
- go build -v
database:
override:
- mysql -u root -e "CREATE DATABASE core_test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"
test:
override:
# './...' is a relative pattern which means all subdirectories
- go test -v -race

156
vendor/github.com/go-xorm/core/column.go generated vendored Normal file
View File

@ -0,0 +1,156 @@
package core
import (
"fmt"
"reflect"
"strings"
"time"
)
const (
TWOSIDES = iota + 1
ONLYTODB
ONLYFROMDB
)
// database column
type Column struct {
Name string
TableName string
FieldName string
SQLType SQLType
Length int
Length2 int
Nullable bool
Default string
Indexes map[string]int
IsPrimaryKey bool
IsAutoIncrement bool
MapType int
IsCreated bool
IsUpdated bool
IsDeleted bool
IsCascade bool
IsVersion bool
DefaultIsEmpty bool
EnumOptions map[string]int
SetOptions map[string]int
DisableTimeZone bool
TimeZone *time.Location // column specified time zone
}
func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable bool) *Column {
return &Column{
Name: name,
TableName: "",
FieldName: fieldName,
SQLType: sqlType,
Length: len1,
Length2: len2,
Nullable: nullable,
Default: "",
Indexes: make(map[string]int),
IsPrimaryKey: false,
IsAutoIncrement: false,
MapType: TWOSIDES,
IsCreated: false,
IsUpdated: false,
IsDeleted: false,
IsCascade: false,
IsVersion: false,
DefaultIsEmpty: false,
EnumOptions: make(map[string]int),
}
}
// generate column description string according dialect
func (col *Column) String(d Dialect) string {
sql := d.QuoteStr() + col.Name + d.QuoteStr() + " "
sql += d.SqlType(col) + " "
if col.IsPrimaryKey {
sql += "PRIMARY KEY "
if col.IsAutoIncrement {
sql += d.AutoIncrStr() + " "
}
}
if d.ShowCreateNull() {
if col.Nullable {
sql += "NULL "
} else {
sql += "NOT NULL "
}
}
if col.Default != "" {
sql += "DEFAULT " + col.Default + " "
}
return sql
}
func (col *Column) StringNoPk(d Dialect) string {
sql := d.QuoteStr() + col.Name + d.QuoteStr() + " "
sql += d.SqlType(col) + " "
if d.ShowCreateNull() {
if col.Nullable {
sql += "NULL "
} else {
sql += "NOT NULL "
}
}
if col.Default != "" {
sql += "DEFAULT " + col.Default + " "
}
return sql
}
// return col's filed of struct's value
func (col *Column) ValueOf(bean interface{}) (*reflect.Value, error) {
dataStruct := reflect.Indirect(reflect.ValueOf(bean))
return col.ValueOfV(&dataStruct)
}
func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) {
var fieldValue reflect.Value
fieldPath := strings.Split(col.FieldName, ".")
if dataStruct.Type().Kind() == reflect.Map {
keyValue := reflect.ValueOf(fieldPath[len(fieldPath)-1])
fieldValue = dataStruct.MapIndex(keyValue)
return &fieldValue, nil
} else if dataStruct.Type().Kind() == reflect.Interface {
structValue := reflect.ValueOf(dataStruct.Interface())
dataStruct = &structValue
}
level := len(fieldPath)
fieldValue = dataStruct.FieldByName(fieldPath[0])
for i := 0; i < level-1; i++ {
if !fieldValue.IsValid() {
break
}
if fieldValue.Kind() == reflect.Struct {
fieldValue = fieldValue.FieldByName(fieldPath[i+1])
} else if fieldValue.Kind() == reflect.Ptr {
if fieldValue.IsNil() {
fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
}
fieldValue = fieldValue.Elem().FieldByName(fieldPath[i+1])
} else {
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
}
}
if !fieldValue.IsValid() {
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
}
return &fieldValue, nil
}

8
vendor/github.com/go-xorm/core/converstion.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
package core
// Conversion is an interface. A type implements Conversion will according
// the custom method to fill into database and retrieve from database.
type Conversion interface {
FromDB([]byte) error
ToDB() ([]byte, error)
}

368
vendor/github.com/go-xorm/core/db.go generated vendored Normal file
View File

@ -0,0 +1,368 @@
package core
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"reflect"
"regexp"
)
func MapToSlice(query string, mp interface{}) (string, []interface{}, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return "", []interface{}{}, ErrNoMapPointer
}
args := make([]interface{}, 0, len(vv.Elem().MapKeys()))
var err error
query = re.ReplaceAllStringFunc(query, func(src string) string {
v := vv.Elem().MapIndex(reflect.ValueOf(src[1:]))
if !v.IsValid() {
err = fmt.Errorf("map key %s is missing", src[1:])
} else {
args = append(args, v.Interface())
}
return "?"
})
return query, args, err
}
func StructToSlice(query string, st interface{}) (string, []interface{}, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return "", []interface{}{}, ErrNoStructPointer
}
args := make([]interface{}, 0)
var err error
query = re.ReplaceAllStringFunc(query, func(src string) string {
fv := vv.Elem().FieldByName(src[1:]).Interface()
if v, ok := fv.(driver.Valuer); ok {
var value driver.Value
value, err = v.Value()
if err != nil {
return "?"
}
args = append(args, value)
} else {
args = append(args, fv)
}
return "?"
})
if err != nil {
return "", []interface{}{}, err
}
return query, args, nil
}
type DB struct {
*sql.DB
Mapper IMapper
}
func Open(driverName, dataSourceName string) (*DB, error) {
db, err := sql.Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
return &DB{db, NewCacheMapper(&SnakeMapper{})}, nil
}
func FromDB(db *sql.DB) *DB {
return &DB{db, NewCacheMapper(&SnakeMapper{})}
}
func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
rows, err := db.DB.Query(query, args...)
if err != nil {
if rows != nil {
rows.Close()
}
return nil, err
}
return &Rows{rows, db.Mapper}, nil
}
func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) {
query, args, err := MapToSlice(query, mp)
if err != nil {
return nil, err
}
return db.Query(query, args...)
}
func (db *DB) QueryStruct(query string, st interface{}) (*Rows, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return db.Query(query, args...)
}
func (db *DB) QueryRow(query string, args ...interface{}) *Row {
rows, err := db.Query(query, args...)
if err != nil {
return &Row{nil, err}
}
return &Row{rows, nil}
}
func (db *DB) QueryRowMap(query string, mp interface{}) *Row {
query, args, err := MapToSlice(query, mp)
if err != nil {
return &Row{nil, err}
}
return db.QueryRow(query, args...)
}
func (db *DB) QueryRowStruct(query string, st interface{}) *Row {
query, args, err := StructToSlice(query, st)
if err != nil {
return &Row{nil, err}
}
return db.QueryRow(query, args...)
}
type Stmt struct {
*sql.Stmt
Mapper IMapper
names map[string]int
}
func (db *DB) Prepare(query string) (*Stmt, error) {
names := make(map[string]int)
var i int
query = re.ReplaceAllStringFunc(query, func(src string) string {
names[src[1:]] = i
i += 1
return "?"
})
stmt, err := db.DB.Prepare(query)
if err != nil {
return nil, err
}
return &Stmt{stmt, db.Mapper, names}, nil
}
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.Stmt.Exec(args...)
}
func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.Stmt.Exec(args...)
}
func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
rows, err := s.Stmt.Query(args...)
if err != nil {
return nil, err
}
return &Rows{rows, s.Mapper}, nil
}
func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.Query(args...)
}
func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.Query(args...)
}
func (s *Stmt) QueryRow(args ...interface{}) *Row {
rows, err := s.Query(args...)
return &Row{rows, err}
}
func (s *Stmt) QueryRowMap(mp interface{}) *Row {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return &Row{nil, errors.New("mp should be a map's pointer")}
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.QueryRow(args...)
}
func (s *Stmt) QueryRowStruct(st interface{}) *Row {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return &Row{nil, errors.New("st should be a struct's pointer")}
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.QueryRow(args...)
}
var (
re = regexp.MustCompile(`[?](\w+)`)
)
// insert into (name) values (?)
// insert into (name) values (?name)
func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) {
query, args, err := MapToSlice(query, mp)
if err != nil {
return nil, err
}
return db.DB.Exec(query, args...)
}
func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return db.DB.Exec(query, args...)
}
type EmptyScanner struct {
}
func (EmptyScanner) Scan(src interface{}) error {
return nil
}
type Tx struct {
*sql.Tx
Mapper IMapper
}
func (db *DB) Begin() (*Tx, error) {
tx, err := db.DB.Begin()
if err != nil {
return nil, err
}
return &Tx{tx, db.Mapper}, nil
}
func (tx *Tx) Prepare(query string) (*Stmt, error) {
names := make(map[string]int)
var i int
query = re.ReplaceAllStringFunc(query, func(src string) string {
names[src[1:]] = i
i += 1
return "?"
})
stmt, err := tx.Tx.Prepare(query)
if err != nil {
return nil, err
}
return &Stmt{stmt, tx.Mapper, names}, nil
}
func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
// TODO:
return stmt
}
func (tx *Tx) ExecMap(query string, mp interface{}) (sql.Result, error) {
query, args, err := MapToSlice(query, mp)
if err != nil {
return nil, err
}
return tx.Tx.Exec(query, args...)
}
func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return tx.Tx.Exec(query, args...)
}
func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
rows, err := tx.Tx.Query(query, args...)
if err != nil {
return nil, err
}
return &Rows{rows, tx.Mapper}, nil
}
func (tx *Tx) QueryMap(query string, mp interface{}) (*Rows, error) {
query, args, err := MapToSlice(query, mp)
if err != nil {
return nil, err
}
return tx.Query(query, args...)
}
func (tx *Tx) QueryStruct(query string, st interface{}) (*Rows, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return tx.Query(query, args...)
}
func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
rows, err := tx.Query(query, args...)
return &Row{rows, err}
}
func (tx *Tx) QueryRowMap(query string, mp interface{}) *Row {
query, args, err := MapToSlice(query, mp)
if err != nil {
return &Row{nil, err}
}
return tx.QueryRow(query, args...)
}
func (tx *Tx) QueryRowStruct(query string, st interface{}) *Row {
query, args, err := StructToSlice(query, st)
if err != nil {
return &Row{nil, err}
}
return tx.QueryRow(query, args...)
}

307
vendor/github.com/go-xorm/core/dialect.go generated vendored Normal file
View File

@ -0,0 +1,307 @@
package core
import (
"fmt"
"strings"
"time"
)
type DbType string
type Uri struct {
DbType DbType
Proto string
Host string
Port string
DbName string
User string
Passwd string
Charset string
Laddr string
Raddr string
Timeout time.Duration
Schema string
}
// a dialect is a driver's wrapper
type Dialect interface {
SetLogger(logger ILogger)
Init(*DB, *Uri, string, string) error
URI() *Uri
DB() *DB
DBType() DbType
SqlType(*Column) string
FormatBytes(b []byte) string
DriverName() string
DataSourceName() string
QuoteStr() string
IsReserved(string) bool
Quote(string) string
AndStr() string
OrStr() string
EqStr() string
RollBackStr() string
AutoIncrStr() string
SupportInsertMany() bool
SupportEngine() bool
SupportCharset() bool
SupportDropIfExists() bool
IndexOnTable() bool
ShowCreateNull() bool
IndexCheckSql(tableName, idxName string) (string, []interface{})
TableCheckSql(tableName string) (string, []interface{})
IsColumnExist(tableName string, colName string) (bool, error)
CreateTableSql(table *Table, tableName, storeEngine, charset string) string
DropTableSql(tableName string) string
CreateIndexSql(tableName string, index *Index) string
DropIndexSql(tableName string, index *Index) string
ModifyColumnSql(tableName string, col *Column) string
ForUpdateSql(query string) string
//CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error
//MustDropTable(tableName string) error
GetColumns(tableName string) ([]string, map[string]*Column, error)
GetTables() ([]*Table, error)
GetIndexes(tableName string) (map[string]*Index, error)
Filters() []Filter
}
func OpenDialect(dialect Dialect) (*DB, error) {
return Open(dialect.DriverName(), dialect.DataSourceName())
}
type Base struct {
db *DB
dialect Dialect
driverName string
dataSourceName string
logger ILogger
*Uri
}
func (b *Base) DB() *DB {
return b.db
}
func (b *Base) SetLogger(logger ILogger) {
b.logger = logger
}
func (b *Base) Init(db *DB, dialect Dialect, uri *Uri, drivername, dataSourceName string) error {
b.db, b.dialect, b.Uri = db, dialect, uri
b.driverName, b.dataSourceName = drivername, dataSourceName
return nil
}
func (b *Base) URI() *Uri {
return b.Uri
}
func (b *Base) DBType() DbType {
return b.Uri.DbType
}
func (b *Base) FormatBytes(bs []byte) string {
return fmt.Sprintf("0x%x", bs)
}
func (b *Base) DriverName() string {
return b.driverName
}
func (b *Base) ShowCreateNull() bool {
return true
}
func (b *Base) DataSourceName() string {
return b.dataSourceName
}
func (b *Base) AndStr() string {
return "AND"
}
func (b *Base) OrStr() string {
return "OR"
}
func (b *Base) EqStr() string {
return "="
}
func (db *Base) RollBackStr() string {
return "ROLL BACK"
}
func (db *Base) SupportDropIfExists() bool {
return true
}
func (db *Base) DropTableSql(tableName string) string {
return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
}
func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
db.LogSQL(query, args)
rows, err := db.DB().Query(query, args...)
if err != nil {
return false, err
}
defer rows.Close()
if rows.Next() {
return true, nil
}
return false, nil
}
func (db *Base) IsColumnExist(tableName, colName string) (bool, error) {
query := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
query = strings.Replace(query, "`", db.dialect.QuoteStr(), -1)
return db.HasRecords(query, db.DbName, tableName, colName)
}
/*
func (db *Base) CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error {
sql, args := db.dialect.TableCheckSql(tableName)
rows, err := db.DB().Query(sql, args...)
if db.Logger != nil {
db.Logger.Info("[sql]", sql, args)
}
if err != nil {
return err
}
defer rows.Close()
if rows.Next() {
return nil
}
sql = db.dialect.CreateTableSql(table, tableName, storeEngine, charset)
_, err = db.DB().Exec(sql)
if db.Logger != nil {
db.Logger.Info("[sql]", sql)
}
return err
}*/
func (db *Base) CreateIndexSql(tableName string, index *Index) string {
quote := db.dialect.Quote
var unique string
var idxName string
if index.Type == UniqueType {
unique = " UNIQUE"
}
idxName = index.XName(tableName)
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
quote(idxName), quote(tableName),
quote(strings.Join(index.Cols, quote(","))))
}
func (db *Base) DropIndexSql(tableName string, index *Index) string {
quote := db.dialect.Quote
var name string
if index.IsRegular {
name = index.XName(tableName)
} else {
name = index.Name
}
return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
}
func (db *Base) ModifyColumnSql(tableName string, col *Column) string {
return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, col.StringNoPk(db.dialect))
}
func (b *Base) CreateTableSql(table *Table, tableName, storeEngine, charset string) string {
var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
sql += b.dialect.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(b.dialect)
} else {
sql += col.StringNoPk(b.dialect)
}
sql = strings.TrimSpace(sql)
sql += ", "
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += b.dialect.Quote(strings.Join(pkList, b.dialect.Quote(",")))
sql += " ), "
}
sql = sql[:len(sql)-2]
}
sql += ")"
if b.dialect.SupportEngine() && storeEngine != "" {
sql += " ENGINE=" + storeEngine
}
if b.dialect.SupportCharset() {
if len(charset) == 0 {
charset = b.dialect.URI().Charset
}
if len(charset) > 0 {
sql += " DEFAULT CHARSET " + charset
}
}
return sql
}
func (b *Base) ForUpdateSql(query string) string {
return query + " FOR UPDATE"
}
func (b *Base) LogSQL(sql string, args []interface{}) {
if b.logger != nil && b.logger.IsShowSQL() {
if len(args) > 0 {
b.logger.Info("[sql]", sql, args)
} else {
b.logger.Info("[sql]", sql)
}
}
}
var (
dialects = map[string]func() Dialect{}
)
// RegisterDialect register database dialect
func RegisterDialect(dbName DbType, dialectFunc func() Dialect) {
if dialectFunc == nil {
panic("core: Register dialect is nil")
}
dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
}
// QueryDialect query if registed database dialect
func QueryDialect(dbName DbType) Dialect {
if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
return d()
}
return nil
}

27
vendor/github.com/go-xorm/core/driver.go generated vendored Normal file
View File

@ -0,0 +1,27 @@
package core
type Driver interface {
Parse(string, string) (*Uri, error)
}
var (
drivers = map[string]Driver{}
)
func RegisterDriver(driverName string, driver Driver) {
if driver == nil {
panic("core: Register driver is nil")
}
if _, dup := drivers[driverName]; dup {
panic("core: Register called twice for driver " + driverName)
}
drivers[driverName] = driver
}
func QueryDriver(driverName string) Driver {
return drivers[driverName]
}
func RegisteredDriverSize() int {
return len(drivers)
}

8
vendor/github.com/go-xorm/core/error.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
package core
import "errors"
var (
ErrNoMapPointer = errors.New("mp should be a map's pointer")
ErrNoStructPointer = errors.New("mp should be a struct's pointer")
)

64
vendor/github.com/go-xorm/core/filter.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package core
import (
"fmt"
"strings"
)
// Filter is an interface to filter SQL
type Filter interface {
Do(sql string, dialect Dialect, table *Table) string
}
// QuoteFilter filter SQL replace ` to database's own quote character
type QuoteFilter struct {
}
func (s *QuoteFilter) Do(sql string, dialect Dialect, table *Table) string {
return strings.Replace(sql, "`", dialect.QuoteStr(), -1)
}
// IdFilter filter SQL replace (id) to primary key column name
type IdFilter struct {
}
type Quoter struct {
dialect Dialect
}
func NewQuoter(dialect Dialect) *Quoter {
return &Quoter{dialect}
}
func (q *Quoter) Quote(content string) string {
return q.dialect.QuoteStr() + content + q.dialect.QuoteStr()
}
func (i *IdFilter) Do(sql string, dialect Dialect, table *Table) string {
quoter := NewQuoter(dialect)
if table != nil && len(table.PrimaryKeys) == 1 {
sql = strings.Replace(sql, "`(id)`", quoter.Quote(table.PrimaryKeys[0]), -1)
sql = strings.Replace(sql, quoter.Quote("(id)"), quoter.Quote(table.PrimaryKeys[0]), -1)
return strings.Replace(sql, "(id)", quoter.Quote(table.PrimaryKeys[0]), -1)
}
return sql
}
// SeqFilter filter SQL replace ?, ? ... to $1, $2 ...
type SeqFilter struct {
Prefix string
Start int
}
func (s *SeqFilter) Do(sql string, dialect Dialect, table *Table) string {
segs := strings.Split(sql, "?")
size := len(segs)
res := ""
for i, c := range segs {
if i < size-1 {
res += c + fmt.Sprintf("%s%v", s.Prefix, i+s.Start)
}
}
res += segs[size-1]
return res
}

31
vendor/github.com/go-xorm/core/ilogger.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
package core
type LogLevel int
const (
// !nashtsai! following level also match syslog.Priority value
LOG_DEBUG LogLevel = iota
LOG_INFO
LOG_WARNING
LOG_ERR
LOG_OFF
LOG_UNKNOWN
)
// logger interface
type ILogger interface {
Debug(v ...interface{})
Debugf(format string, v ...interface{})
Error(v ...interface{})
Errorf(format string, v ...interface{})
Info(v ...interface{})
Infof(format string, v ...interface{})
Warn(v ...interface{})
Warnf(format string, v ...interface{})
Level() LogLevel
SetLevel(l LogLevel)
ShowSQL(show ...bool)
IsShowSQL() bool
}

61
vendor/github.com/go-xorm/core/index.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
package core
import (
"fmt"
"sort"
"strings"
)
const (
IndexType = iota + 1
UniqueType
)
// database index
type Index struct {
IsRegular bool
Name string
Type int
Cols []string
}
func (index *Index) XName(tableName string) string {
if !strings.HasPrefix(index.Name, "UQE_") &&
!strings.HasPrefix(index.Name, "IDX_") {
if index.Type == UniqueType {
return fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
}
return fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
}
return index.Name
}
// add columns which will be composite index
func (index *Index) AddColumn(cols ...string) {
for _, col := range cols {
index.Cols = append(index.Cols, col)
}
}
func (index *Index) Equal(dst *Index) bool {
if index.Type != dst.Type {
return false
}
if len(index.Cols) != len(dst.Cols) {
return false
}
sort.StringSlice(index.Cols).Sort()
sort.StringSlice(dst.Cols).Sort()
for i := 0; i < len(index.Cols); i++ {
if index.Cols[i] != dst.Cols[i] {
return false
}
}
return true
}
// new an index
func NewIndex(name string, indexType int) *Index {
return &Index{true, name, indexType, make([]string, 0)}
}

254
vendor/github.com/go-xorm/core/mapper.go generated vendored Normal file
View File

@ -0,0 +1,254 @@
package core
import (
"strings"
"sync"
)
// name translation between struct, fields names and table, column names
type IMapper interface {
Obj2Table(string) string
Table2Obj(string) string
}
type CacheMapper struct {
oriMapper IMapper
obj2tableCache map[string]string
obj2tableMutex sync.RWMutex
table2objCache map[string]string
table2objMutex sync.RWMutex
}
func NewCacheMapper(mapper IMapper) *CacheMapper {
return &CacheMapper{oriMapper: mapper, obj2tableCache: make(map[string]string),
table2objCache: make(map[string]string),
}
}
func (m *CacheMapper) Obj2Table(o string) string {
m.obj2tableMutex.RLock()
t, ok := m.obj2tableCache[o]
m.obj2tableMutex.RUnlock()
if ok {
return t
}
t = m.oriMapper.Obj2Table(o)
m.obj2tableMutex.Lock()
m.obj2tableCache[o] = t
m.obj2tableMutex.Unlock()
return t
}
func (m *CacheMapper) Table2Obj(t string) string {
m.table2objMutex.RLock()
o, ok := m.table2objCache[t]
m.table2objMutex.RUnlock()
if ok {
return o
}
o = m.oriMapper.Table2Obj(t)
m.table2objMutex.Lock()
m.table2objCache[t] = o
m.table2objMutex.Unlock()
return o
}
// SameMapper implements IMapper and provides same name between struct and
// database table
type SameMapper struct {
}
func (m SameMapper) Obj2Table(o string) string {
return o
}
func (m SameMapper) Table2Obj(t string) string {
return t
}
// SnakeMapper implements IMapper and provides name transaltion between
// struct and database table
type SnakeMapper struct {
}
func snakeCasedName(name string) string {
newstr := make([]rune, 0)
for idx, chr := range name {
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
if idx > 0 {
newstr = append(newstr, '_')
}
chr -= ('A' - 'a')
}
newstr = append(newstr, chr)
}
return string(newstr)
}
func (mapper SnakeMapper) Obj2Table(name string) string {
return snakeCasedName(name)
}
func titleCasedName(name string) string {
newstr := make([]rune, 0)
upNextChar := true
name = strings.ToLower(name)
for _, chr := range name {
switch {
case upNextChar:
upNextChar = false
if 'a' <= chr && chr <= 'z' {
chr -= ('a' - 'A')
}
case chr == '_':
upNextChar = true
continue
}
newstr = append(newstr, chr)
}
return string(newstr)
}
func (mapper SnakeMapper) Table2Obj(name string) string {
return titleCasedName(name)
}
// GonicMapper implements IMapper. It will consider initialisms when mapping names.
// E.g. id -> ID, user -> User and to table names: UserID -> user_id, MyUID -> my_uid
type GonicMapper map[string]bool
func isASCIIUpper(r rune) bool {
return 'A' <= r && r <= 'Z'
}
func toASCIIUpper(r rune) rune {
if 'a' <= r && r <= 'z' {
r -= ('a' - 'A')
}
return r
}
func gonicCasedName(name string) string {
newstr := make([]rune, 0, len(name)+3)
for idx, chr := range name {
if isASCIIUpper(chr) && idx > 0 {
if !isASCIIUpper(newstr[len(newstr)-1]) {
newstr = append(newstr, '_')
}
}
if !isASCIIUpper(chr) && idx > 1 {
l := len(newstr)
if isASCIIUpper(newstr[l-1]) && isASCIIUpper(newstr[l-2]) {
newstr = append(newstr, newstr[l-1])
newstr[l-1] = '_'
}
}
newstr = append(newstr, chr)
}
return strings.ToLower(string(newstr))
}
func (mapper GonicMapper) Obj2Table(name string) string {
return gonicCasedName(name)
}
func (mapper GonicMapper) Table2Obj(name string) string {
newstr := make([]rune, 0)
name = strings.ToLower(name)
parts := strings.Split(name, "_")
for _, p := range parts {
_, isInitialism := mapper[strings.ToUpper(p)]
for i, r := range p {
if i == 0 || isInitialism {
r = toASCIIUpper(r)
}
newstr = append(newstr, r)
}
}
return string(newstr)
}
// A GonicMapper that contains a list of common initialisms taken from golang/lint
var LintGonicMapper = GonicMapper{
"API": true,
"ASCII": true,
"CPU": true,
"CSS": true,
"DNS": true,
"EOF": true,
"GUID": true,
"HTML": true,
"HTTP": true,
"HTTPS": true,
"ID": true,
"IP": true,
"JSON": true,
"LHS": true,
"QPS": true,
"RAM": true,
"RHS": true,
"RPC": true,
"SLA": true,
"SMTP": true,
"SSH": true,
"TLS": true,
"TTL": true,
"UI": true,
"UID": true,
"UUID": true,
"URI": true,
"URL": true,
"UTF8": true,
"VM": true,
"XML": true,
"XSRF": true,
"XSS": true,
}
// provide prefix table name support
type PrefixMapper struct {
Mapper IMapper
Prefix string
}
func (mapper PrefixMapper) Obj2Table(name string) string {
return mapper.Prefix + mapper.Mapper.Obj2Table(name)
}
func (mapper PrefixMapper) Table2Obj(name string) string {
return mapper.Mapper.Table2Obj(name[len(mapper.Prefix):])
}
func NewPrefixMapper(mapper IMapper, prefix string) PrefixMapper {
return PrefixMapper{mapper, prefix}
}
// provide suffix table name support
type SuffixMapper struct {
Mapper IMapper
Suffix string
}
func (mapper SuffixMapper) Obj2Table(name string) string {
return mapper.Mapper.Obj2Table(name) + mapper.Suffix
}
func (mapper SuffixMapper) Table2Obj(name string) string {
return mapper.Mapper.Table2Obj(name[:len(name)-len(mapper.Suffix)])
}
func NewSuffixMapper(mapper IMapper, suffix string) SuffixMapper {
return SuffixMapper{mapper, suffix}
}

26
vendor/github.com/go-xorm/core/pk.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
package core
import (
"bytes"
"encoding/gob"
)
type PK []interface{}
func NewPK(pks ...interface{}) *PK {
p := PK(pks)
return &p
}
func (p *PK) ToString() (string, error) {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
err := enc.Encode(*p)
return buf.String(), err
}
func (p *PK) FromString(content string) error {
dec := gob.NewDecoder(bytes.NewBufferString(content))
err := dec.Decode(p)
return err
}

380
vendor/github.com/go-xorm/core/rows.go generated vendored Normal file
View File

@ -0,0 +1,380 @@
package core
import (
"database/sql"
"errors"
"reflect"
"sync"
)
type Rows struct {
*sql.Rows
Mapper IMapper
}
func (rs *Rows) ToMapString() ([]map[string]string, error) {
cols, err := rs.Columns()
if err != nil {
return nil, err
}
var results = make([]map[string]string, 0, 10)
for rs.Next() {
var record = make(map[string]string, len(cols))
err = rs.ScanMap(&record)
if err != nil {
return nil, err
}
results = append(results, record)
}
return results, nil
}
// scan data to a struct's pointer according field index
func (rs *Rows) ScanStructByIndex(dest ...interface{}) error {
if len(dest) == 0 {
return errors.New("at least one struct")
}
vvvs := make([]reflect.Value, len(dest))
for i, s := range dest {
vv := reflect.ValueOf(s)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return errors.New("dest should be a struct's pointer")
}
vvvs[i] = vv.Elem()
}
cols, err := rs.Columns()
if err != nil {
return err
}
newDest := make([]interface{}, len(cols))
var i = 0
for _, vvv := range vvvs {
for j := 0; j < vvv.NumField(); j++ {
newDest[i] = vvv.Field(j).Addr().Interface()
i = i + 1
}
}
return rs.Rows.Scan(newDest...)
}
var (
fieldCache = make(map[reflect.Type]map[string]int)
fieldCacheMutex sync.RWMutex
)
func fieldByName(v reflect.Value, name string) reflect.Value {
t := v.Type()
fieldCacheMutex.RLock()
cache, ok := fieldCache[t]
fieldCacheMutex.RUnlock()
if !ok {
cache = make(map[string]int)
for i := 0; i < v.NumField(); i++ {
cache[t.Field(i).Name] = i
}
fieldCacheMutex.Lock()
fieldCache[t] = cache
fieldCacheMutex.Unlock()
}
if i, ok := cache[name]; ok {
return v.Field(i)
}
return reflect.Zero(t)
}
// scan data to a struct's pointer according field name
func (rs *Rows) ScanStructByName(dest interface{}) error {
vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return errors.New("dest should be a struct's pointer")
}
cols, err := rs.Columns()
if err != nil {
return err
}
newDest := make([]interface{}, len(cols))
var v EmptyScanner
for j, name := range cols {
f := fieldByName(vv.Elem(), rs.Mapper.Table2Obj(name))
if f.IsValid() {
newDest[j] = f.Addr().Interface()
} else {
newDest[j] = &v
}
}
return rs.Rows.Scan(newDest...)
}
type cacheStruct struct {
value reflect.Value
idx int
}
var (
reflectCache = make(map[reflect.Type]*cacheStruct)
reflectCacheMutex sync.RWMutex
)
func ReflectNew(typ reflect.Type) reflect.Value {
reflectCacheMutex.RLock()
cs, ok := reflectCache[typ]
reflectCacheMutex.RUnlock()
const newSize = 200
if !ok || cs.idx+1 > newSize-1 {
cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), newSize, newSize), 0}
reflectCacheMutex.Lock()
reflectCache[typ] = cs
reflectCacheMutex.Unlock()
} else {
reflectCacheMutex.Lock()
cs.idx = cs.idx + 1
reflectCacheMutex.Unlock()
}
return cs.value.Index(cs.idx).Addr()
}
// scan data to a slice's pointer, slice's length should equal to columns' number
func (rs *Rows) ScanSlice(dest interface{}) error {
vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice {
return errors.New("dest should be a slice's pointer")
}
vvv := vv.Elem()
cols, err := rs.Columns()
if err != nil {
return err
}
newDest := make([]interface{}, len(cols))
for j := 0; j < len(cols); j++ {
if j >= vvv.Len() {
newDest[j] = reflect.New(vvv.Type().Elem()).Interface()
} else {
newDest[j] = vvv.Index(j).Addr().Interface()
}
}
err = rs.Rows.Scan(newDest...)
if err != nil {
return err
}
srcLen := vvv.Len()
for i := srcLen; i < len(cols); i++ {
vvv = reflect.Append(vvv, reflect.ValueOf(newDest[i]).Elem())
}
return nil
}
// scan data to a map's pointer
func (rs *Rows) ScanMap(dest interface{}) error {
vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return errors.New("dest should be a map's pointer")
}
cols, err := rs.Columns()
if err != nil {
return err
}
newDest := make([]interface{}, len(cols))
vvv := vv.Elem()
for i, _ := range cols {
newDest[i] = ReflectNew(vvv.Type().Elem()).Interface()
//v := reflect.New(vvv.Type().Elem())
//newDest[i] = v.Interface()
}
err = rs.Rows.Scan(newDest...)
if err != nil {
return err
}
for i, name := range cols {
vname := reflect.ValueOf(name)
vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem())
}
return nil
}
/*func (rs *Rows) ScanMap(dest interface{}) error {
vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return errors.New("dest should be a map's pointer")
}
cols, err := rs.Columns()
if err != nil {
return err
}
newDest := make([]interface{}, len(cols))
err = rs.ScanSlice(newDest)
if err != nil {
return err
}
vvv := vv.Elem()
for i, name := range cols {
vname := reflect.ValueOf(name)
vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem())
}
return nil
}*/
type Row struct {
rows *Rows
// One of these two will be non-nil:
err error // deferred error for easy chaining
}
func (row *Row) Columns() ([]string, error) {
if row.err != nil {
return nil, row.err
}
return row.rows.Columns()
}
func (row *Row) Scan(dest ...interface{}) error {
if row.err != nil {
return row.err
}
defer row.rows.Close()
for _, dp := range dest {
if _, ok := dp.(*sql.RawBytes); ok {
return errors.New("sql: RawBytes isn't allowed on Row.Scan")
}
}
if !row.rows.Next() {
if err := row.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
err := row.rows.Scan(dest...)
if err != nil {
return err
}
// Make sure the query can be processed to completion with no errors.
return row.rows.Close()
}
func (row *Row) ScanStructByName(dest interface{}) error {
if row.err != nil {
return row.err
}
defer row.rows.Close()
if !row.rows.Next() {
if err := row.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
err := row.rows.ScanStructByName(dest)
if err != nil {
return err
}
// Make sure the query can be processed to completion with no errors.
return row.rows.Close()
}
func (row *Row) ScanStructByIndex(dest interface{}) error {
if row.err != nil {
return row.err
}
defer row.rows.Close()
if !row.rows.Next() {
if err := row.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
err := row.rows.ScanStructByIndex(dest)
if err != nil {
return err
}
// Make sure the query can be processed to completion with no errors.
return row.rows.Close()
}
// scan data to a slice's pointer, slice's length should equal to columns' number
func (row *Row) ScanSlice(dest interface{}) error {
if row.err != nil {
return row.err
}
defer row.rows.Close()
if !row.rows.Next() {
if err := row.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
err := row.rows.ScanSlice(dest)
if err != nil {
return err
}
// Make sure the query can be processed to completion with no errors.
return row.rows.Close()
}
// scan data to a map's pointer
func (row *Row) ScanMap(dest interface{}) error {
if row.err != nil {
return row.err
}
defer row.rows.Close()
if !row.rows.Next() {
if err := row.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
err := row.rows.ScanMap(dest)
if err != nil {
return err
}
// Make sure the query can be processed to completion with no errors.
return row.rows.Close()
}
func (row *Row) ToMapString() (map[string]string, error) {
cols, err := row.Columns()
if err != nil {
return nil, err
}
var record = make(map[string]string, len(cols))
err = row.ScanMap(&record)
if err != nil {
return nil, err
}
return record, nil
}

52
vendor/github.com/go-xorm/core/scan.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
package core
import (
"database/sql/driver"
"fmt"
"time"
)
type NullTime time.Time
var (
_ driver.Valuer = NullTime{}
)
func (ns *NullTime) Scan(value interface{}) error {
if value == nil {
return nil
}
return convertTime(ns, value)
}
// Value implements the driver Valuer interface.
func (ns NullTime) Value() (driver.Value, error) {
if (time.Time)(ns).IsZero() {
return nil, nil
}
return (time.Time)(ns).Format("2006-01-02 15:04:05"), nil
}
func convertTime(dest *NullTime, src interface{}) error {
// Common cases, without reflect.
switch s := src.(type) {
case string:
t, err := time.Parse("2006-01-02 15:04:05", s)
if err != nil {
return err
}
*dest = NullTime(t)
return nil
case []uint8:
t, err := time.Parse("2006-01-02 15:04:05", string(s))
if err != nil {
return err
}
*dest = NullTime(t)
return nil
case nil:
default:
return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
}
return nil
}

151
vendor/github.com/go-xorm/core/table.go generated vendored Normal file
View File

@ -0,0 +1,151 @@
package core
import (
"reflect"
"strings"
)
// database table
type Table struct {
Name string
Type reflect.Type
columnsSeq []string
columnsMap map[string][]*Column
columns []*Column
Indexes map[string]*Index
PrimaryKeys []string
AutoIncrement string
Created map[string]bool
Updated string
Deleted string
Version string
Cacher Cacher
StoreEngine string
Charset string
}
func (table *Table) Columns() []*Column {
return table.columns
}
func (table *Table) ColumnsSeq() []string {
return table.columnsSeq
}
func NewEmptyTable() *Table {
return NewTable("", nil)
}
func NewTable(name string, t reflect.Type) *Table {
return &Table{Name: name, Type: t,
columnsSeq: make([]string, 0),
columns: make([]*Column, 0),
columnsMap: make(map[string][]*Column),
Indexes: make(map[string]*Index),
Created: make(map[string]bool),
PrimaryKeys: make([]string, 0),
}
}
func (table *Table) columnsByName(name string) []*Column {
n := len(name)
for k := range table.columnsMap {
if len(k) != n {
continue
}
if strings.EqualFold(k, name) {
return table.columnsMap[k]
}
}
return nil
}
func (table *Table) GetColumn(name string) *Column {
cols := table.columnsByName(name)
if cols != nil {
return cols[0]
}
return nil
}
func (table *Table) GetColumnIdx(name string, idx int) *Column {
cols := table.columnsByName(name)
if cols != nil && idx < len(cols) {
return cols[idx]
}
return nil
}
// if has primary key, return column
func (table *Table) PKColumns() []*Column {
columns := make([]*Column, len(table.PrimaryKeys))
for i, name := range table.PrimaryKeys {
columns[i] = table.GetColumn(name)
}
return columns
}
func (table *Table) ColumnType(name string) reflect.Type {
t, _ := table.Type.FieldByName(name)
return t.Type
}
func (table *Table) AutoIncrColumn() *Column {
return table.GetColumn(table.AutoIncrement)
}
func (table *Table) VersionColumn() *Column {
return table.GetColumn(table.Version)
}
func (table *Table) UpdatedColumn() *Column {
return table.GetColumn(table.Updated)
}
func (table *Table) DeletedColumn() *Column {
return table.GetColumn(table.Deleted)
}
// add a column to table
func (table *Table) AddColumn(col *Column) {
table.columnsSeq = append(table.columnsSeq, col.Name)
table.columns = append(table.columns, col)
colName := strings.ToLower(col.Name)
if c, ok := table.columnsMap[colName]; ok {
table.columnsMap[colName] = append(c, col)
} else {
table.columnsMap[colName] = []*Column{col}
}
if col.IsPrimaryKey {
table.PrimaryKeys = append(table.PrimaryKeys, col.Name)
}
if col.IsAutoIncrement {
table.AutoIncrement = col.Name
}
if col.IsCreated {
table.Created[col.Name] = true
}
if col.IsUpdated {
table.Updated = col.Name
}
if col.IsDeleted {
table.Deleted = col.Name
}
if col.IsVersion {
table.Version = col.Name
}
}
// add an index or an unique to table
func (table *Table) AddIndex(index *Index) {
table.Indexes[index.Name] = index
}

304
vendor/github.com/go-xorm/core/type.go generated vendored Normal file
View File

@ -0,0 +1,304 @@
package core
import (
"reflect"
"sort"
"strings"
"time"
)
const (
POSTGRES = "postgres"
SQLITE = "sqlite3"
MYSQL = "mysql"
MSSQL = "mssql"
ORACLE = "oracle"
)
// xorm SQL types
type SQLType struct {
Name string
DefaultLength int
DefaultLength2 int
}
const (
UNKNOW_TYPE = iota
TEXT_TYPE
BLOB_TYPE
TIME_TYPE
NUMERIC_TYPE
)
func (s *SQLType) IsType(st int) bool {
if t, ok := SqlTypes[s.Name]; ok && t == st {
return true
}
return false
}
func (s *SQLType) IsText() bool {
return s.IsType(TEXT_TYPE)
}
func (s *SQLType) IsBlob() bool {
return s.IsType(BLOB_TYPE)
}
func (s *SQLType) IsTime() bool {
return s.IsType(TIME_TYPE)
}
func (s *SQLType) IsNumeric() bool {
return s.IsType(NUMERIC_TYPE)
}
func (s *SQLType) IsJson() bool {
return s.Name == Json || s.Name == Jsonb
}
var (
Bit = "BIT"
TinyInt = "TINYINT"
SmallInt = "SMALLINT"
MediumInt = "MEDIUMINT"
Int = "INT"
Integer = "INTEGER"
BigInt = "BIGINT"
Enum = "ENUM"
Set = "SET"
Char = "CHAR"
Varchar = "VARCHAR"
NVarchar = "NVARCHAR"
TinyText = "TINYTEXT"
Text = "TEXT"
Clob = "CLOB"
MediumText = "MEDIUMTEXT"
LongText = "LONGTEXT"
Uuid = "UUID"
Date = "DATE"
DateTime = "DATETIME"
Time = "TIME"
TimeStamp = "TIMESTAMP"
TimeStampz = "TIMESTAMPZ"
Decimal = "DECIMAL"
Numeric = "NUMERIC"
Real = "REAL"
Float = "FLOAT"
Double = "DOUBLE"
Binary = "BINARY"
VarBinary = "VARBINARY"
TinyBlob = "TINYBLOB"
Blob = "BLOB"
MediumBlob = "MEDIUMBLOB"
LongBlob = "LONGBLOB"
Bytea = "BYTEA"
Bool = "BOOL"
Serial = "SERIAL"
BigSerial = "BIGSERIAL"
Json = "JSON"
Jsonb = "JSONB"
SqlTypes = map[string]int{
Bit: NUMERIC_TYPE,
TinyInt: NUMERIC_TYPE,
SmallInt: NUMERIC_TYPE,
MediumInt: NUMERIC_TYPE,
Int: NUMERIC_TYPE,
Integer: NUMERIC_TYPE,
BigInt: NUMERIC_TYPE,
Enum: TEXT_TYPE,
Set: TEXT_TYPE,
Json: TEXT_TYPE,
Jsonb: TEXT_TYPE,
Char: TEXT_TYPE,
Varchar: TEXT_TYPE,
NVarchar: TEXT_TYPE,
TinyText: TEXT_TYPE,
Text: TEXT_TYPE,
MediumText: TEXT_TYPE,
LongText: TEXT_TYPE,
Uuid: TEXT_TYPE,
Clob: TEXT_TYPE,
Date: TIME_TYPE,
DateTime: TIME_TYPE,
Time: TIME_TYPE,
TimeStamp: TIME_TYPE,
TimeStampz: TIME_TYPE,
Decimal: NUMERIC_TYPE,
Numeric: NUMERIC_TYPE,
Real: NUMERIC_TYPE,
Float: NUMERIC_TYPE,
Double: NUMERIC_TYPE,
Binary: BLOB_TYPE,
VarBinary: BLOB_TYPE,
TinyBlob: BLOB_TYPE,
Blob: BLOB_TYPE,
MediumBlob: BLOB_TYPE,
LongBlob: BLOB_TYPE,
Bytea: BLOB_TYPE,
Bool: NUMERIC_TYPE,
Serial: NUMERIC_TYPE,
BigSerial: NUMERIC_TYPE,
}
intTypes = sort.StringSlice{"*int", "*int16", "*int32", "*int8"}
uintTypes = sort.StringSlice{"*uint", "*uint16", "*uint32", "*uint8"}
)
// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparision
var (
c_EMPTY_STRING string
c_BOOL_DEFAULT bool
c_BYTE_DEFAULT byte
c_COMPLEX64_DEFAULT complex64
c_COMPLEX128_DEFAULT complex128
c_FLOAT32_DEFAULT float32
c_FLOAT64_DEFAULT float64
c_INT64_DEFAULT int64
c_UINT64_DEFAULT uint64
c_INT32_DEFAULT int32
c_UINT32_DEFAULT uint32
c_INT16_DEFAULT int16
c_UINT16_DEFAULT uint16
c_INT8_DEFAULT int8
c_UINT8_DEFAULT uint8
c_INT_DEFAULT int
c_UINT_DEFAULT uint
c_TIME_DEFAULT time.Time
)
var (
IntType = reflect.TypeOf(c_INT_DEFAULT)
Int8Type = reflect.TypeOf(c_INT8_DEFAULT)
Int16Type = reflect.TypeOf(c_INT16_DEFAULT)
Int32Type = reflect.TypeOf(c_INT32_DEFAULT)
Int64Type = reflect.TypeOf(c_INT64_DEFAULT)
UintType = reflect.TypeOf(c_UINT_DEFAULT)
Uint8Type = reflect.TypeOf(c_UINT8_DEFAULT)
Uint16Type = reflect.TypeOf(c_UINT16_DEFAULT)
Uint32Type = reflect.TypeOf(c_UINT32_DEFAULT)
Uint64Type = reflect.TypeOf(c_UINT64_DEFAULT)
Float32Type = reflect.TypeOf(c_FLOAT32_DEFAULT)
Float64Type = reflect.TypeOf(c_FLOAT64_DEFAULT)
Complex64Type = reflect.TypeOf(c_COMPLEX64_DEFAULT)
Complex128Type = reflect.TypeOf(c_COMPLEX128_DEFAULT)
StringType = reflect.TypeOf(c_EMPTY_STRING)
BoolType = reflect.TypeOf(c_BOOL_DEFAULT)
ByteType = reflect.TypeOf(c_BYTE_DEFAULT)
BytesType = reflect.SliceOf(ByteType)
TimeType = reflect.TypeOf(c_TIME_DEFAULT)
)
var (
PtrIntType = reflect.PtrTo(IntType)
PtrInt8Type = reflect.PtrTo(Int8Type)
PtrInt16Type = reflect.PtrTo(Int16Type)
PtrInt32Type = reflect.PtrTo(Int32Type)
PtrInt64Type = reflect.PtrTo(Int64Type)
PtrUintType = reflect.PtrTo(UintType)
PtrUint8Type = reflect.PtrTo(Uint8Type)
PtrUint16Type = reflect.PtrTo(Uint16Type)
PtrUint32Type = reflect.PtrTo(Uint32Type)
PtrUint64Type = reflect.PtrTo(Uint64Type)
PtrFloat32Type = reflect.PtrTo(Float32Type)
PtrFloat64Type = reflect.PtrTo(Float64Type)
PtrComplex64Type = reflect.PtrTo(Complex64Type)
PtrComplex128Type = reflect.PtrTo(Complex128Type)
PtrStringType = reflect.PtrTo(StringType)
PtrBoolType = reflect.PtrTo(BoolType)
PtrByteType = reflect.PtrTo(ByteType)
PtrTimeType = reflect.PtrTo(TimeType)
)
// Type2SQLType generate SQLType acorrding Go's type
func Type2SQLType(t reflect.Type) (st SQLType) {
switch k := t.Kind(); k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
st = SQLType{Int, 0, 0}
case reflect.Int64, reflect.Uint64:
st = SQLType{BigInt, 0, 0}
case reflect.Float32:
st = SQLType{Float, 0, 0}
case reflect.Float64:
st = SQLType{Double, 0, 0}
case reflect.Complex64, reflect.Complex128:
st = SQLType{Varchar, 64, 0}
case reflect.Array, reflect.Slice, reflect.Map:
if t.Elem() == reflect.TypeOf(c_BYTE_DEFAULT) {
st = SQLType{Blob, 0, 0}
} else {
st = SQLType{Text, 0, 0}
}
case reflect.Bool:
st = SQLType{Bool, 0, 0}
case reflect.String:
st = SQLType{Varchar, 255, 0}
case reflect.Struct:
if t.ConvertibleTo(TimeType) {
st = SQLType{DateTime, 0, 0}
} else {
// TODO need to handle association struct
st = SQLType{Text, 0, 0}
}
case reflect.Ptr:
st = Type2SQLType(t.Elem())
default:
st = SQLType{Text, 0, 0}
}
return
}
// default sql type change to go types
func SQLType2Type(st SQLType) reflect.Type {
name := strings.ToUpper(st.Name)
switch name {
case Bit, TinyInt, SmallInt, MediumInt, Int, Integer, Serial:
return reflect.TypeOf(1)
case BigInt, BigSerial:
return reflect.TypeOf(int64(1))
case Float, Real:
return reflect.TypeOf(float32(1))
case Double:
return reflect.TypeOf(float64(1))
case Char, Varchar, NVarchar, TinyText, Text, MediumText, LongText, Enum, Set, Uuid, Clob:
return reflect.TypeOf("")
case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary:
return reflect.TypeOf([]byte{})
case Bool:
return reflect.TypeOf(true)
case DateTime, Date, Time, TimeStamp, TimeStampz:
return reflect.TypeOf(c_TIME_DEFAULT)
case Decimal, Numeric:
return reflect.TypeOf("")
default:
return reflect.TypeOf("")
}
}

49
vendor/github.com/go-xorm/xorm/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,49 @@
## Contributing to xorm
`xorm` has a backlog of [pull requests](https://help.github.com/articles/using-pull-requests), but contributions are still very
much welcome. You can help with patch review, submitting bug reports,
or adding new functionality. There is no formal style guide, but
please conform to the style of existing code and general Go formatting
conventions when submitting patches.
* [fork a repo](https://help.github.com/articles/fork-a-repo)
* [creating a pull request ](https://help.github.com/articles/creating-a-pull-request)
### Language
Since `xorm` is a world-wide open source project, please describe your issues or code changes in English as soon as possible.
### Sign your codes with comments
```
// !<you github id>! your comments
e.g.,
// !lunny! this is comments made by lunny
```
### Patch review
Help review existing open [pull requests](https://help.github.com/articles/using-pull-requests) by commenting on the code or
proposed functionality.
### Bug reports
We appreciate any bug reports, but especially ones with self-contained
(doesn't depend on code outside of xorm), minimal (can't be simplified
further) test cases. It's especially helpful if you can submit a pull
request with just the failing test case (you'll probably want to
pattern it after the tests in
[base.go](https://github.com/go-xorm/tests/blob/master/base.go) AND
[benchmark.go](https://github.com/go-xorm/tests/blob/master/benchmark.go).
If you implements a new database interface, you maybe need to add a <databasename>_test.go file.
For example, [mysql_test.go](https://github.com/go-xorm/tests/blob/master/mysql/mysql_test.go)
### New functionality
There are a number of pending patches for new functionality, so
additional feature patches will take a while to merge. Still, patches
are generally reviewed based on usefulness and complexity in addition
to time-in-queue, so if you have a knockout idea, take a shot. Feel
free to open an issue discussion your proposed patch beforehand.

27
vendor/github.com/go-xorm/xorm/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2013 - 2015 The Xorm Authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Some files were not shown because too many files have changed in this diff Show More