summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Unknwon/com
diff options
context:
space:
mode:
authorThomas Boerger <thomas@webhippie.de>2016-11-03 23:16:01 +0100
committerThomas Boerger <thomas@webhippie.de>2016-11-04 08:43:11 +0100
commit1ebb35b98889ff77299f24d82da426b434b0cca0 (patch)
tree6dcb814d6df4d11c7e7a0ba6da8a6945628e2c5d /vendor/github.com/Unknwon/com
parent78f86abba45cb35018c58b8bd5f4c48a86cc8634 (diff)
downloadgitea-1ebb35b98889ff77299f24d82da426b434b0cca0.tar.gz
gitea-1ebb35b98889ff77299f24d82da426b434b0cca0.zip
Added all required dependencies
Diffstat (limited to 'vendor/github.com/Unknwon/com')
-rw-r--r--vendor/github.com/Unknwon/com/LICENSE191
-rw-r--r--vendor/github.com/Unknwon/com/README.md20
-rw-r--r--vendor/github.com/Unknwon/com/cmd.go161
-rw-r--r--vendor/github.com/Unknwon/com/convert.go157
-rw-r--r--vendor/github.com/Unknwon/com/dir.go173
-rw-r--r--vendor/github.com/Unknwon/com/file.go145
-rw-r--r--vendor/github.com/Unknwon/com/html.go60
-rw-r--r--vendor/github.com/Unknwon/com/http.go201
-rw-r--r--vendor/github.com/Unknwon/com/math.go29
-rw-r--r--vendor/github.com/Unknwon/com/path.go80
-rw-r--r--vendor/github.com/Unknwon/com/regex.go56
-rw-r--r--vendor/github.com/Unknwon/com/slice.go87
-rw-r--r--vendor/github.com/Unknwon/com/string.go243
-rw-r--r--vendor/github.com/Unknwon/com/time.go115
-rw-r--r--vendor/github.com/Unknwon/com/url.go41
15 files changed, 1759 insertions, 0 deletions
diff --git a/vendor/github.com/Unknwon/com/LICENSE b/vendor/github.com/Unknwon/com/LICENSE
new file mode 100644
index 0000000000..8405e89a0b
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/LICENSE
@@ -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. \ No newline at end of file
diff --git a/vendor/github.com/Unknwon/com/README.md b/vendor/github.com/Unknwon/com/README.md
new file mode 100644
index 0000000000..8d821abd65
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/README.md
@@ -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** .
diff --git a/vendor/github.com/Unknwon/com/cmd.go b/vendor/github.com/Unknwon/com/cmd.go
new file mode 100644
index 0000000000..dc7086d8f7
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/cmd.go
@@ -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...))
+}
diff --git a/vendor/github.com/Unknwon/com/convert.go b/vendor/github.com/Unknwon/com/convert.go
new file mode 100644
index 0000000000..25b3e0e562
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/convert.go
@@ -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
+}
diff --git a/vendor/github.com/Unknwon/com/dir.go b/vendor/github.com/Unknwon/com/dir.go
new file mode 100644
index 0000000000..c126d79da8
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/dir.go
@@ -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
+}
diff --git a/vendor/github.com/Unknwon/com/file.go b/vendor/github.com/Unknwon/com/file.go
new file mode 100644
index 0000000000..b51502c917
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/file.go
@@ -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)
+}
diff --git a/vendor/github.com/Unknwon/com/html.go b/vendor/github.com/Unknwon/com/html.go
new file mode 100644
index 0000000000..762d94b050
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/html.go
@@ -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)
+}
diff --git a/vendor/github.com/Unknwon/com/http.go b/vendor/github.com/Unknwon/com/http.go
new file mode 100644
index 0000000000..3415059ae9
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/http.go
@@ -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
+}
diff --git a/vendor/github.com/Unknwon/com/math.go b/vendor/github.com/Unknwon/com/math.go
new file mode 100644
index 0000000000..99c56b6594
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/math.go
@@ -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
+ }
+ }
+}
diff --git a/vendor/github.com/Unknwon/com/path.go b/vendor/github.com/Unknwon/com/path.go
new file mode 100644
index 0000000000..b1e860def4
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/path.go
@@ -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
+}
diff --git a/vendor/github.com/Unknwon/com/regex.go b/vendor/github.com/Unknwon/com/regex.go
new file mode 100644
index 0000000000..765bfc4311
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/regex.go
@@ -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)
+}
diff --git a/vendor/github.com/Unknwon/com/slice.go b/vendor/github.com/Unknwon/com/slice.go
new file mode 100644
index 0000000000..27801a4d7d
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/slice.go
@@ -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
+}
diff --git a/vendor/github.com/Unknwon/com/string.go b/vendor/github.com/Unknwon/com/string.go
new file mode 100644
index 0000000000..4c79820f1f
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/string.go
@@ -0,0 +1,243 @@
+// 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"
+ "encoding/base64"
+ "errors"
+ "io"
+ r "math/rand"
+ "strconv"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+// AESEncrypt encrypts text and given key with AES.
+func AESEncrypt(key, text []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+ b := base64.StdEncoding.EncodeToString(text)
+ ciphertext := make([]byte, aes.BlockSize+len(b))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ return nil, err
+ }
+ cfb := cipher.NewCFBEncrypter(block, iv)
+ cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
+ return ciphertext, nil
+}
+
+// AESDecrypt decrypts text and given key with AES.
+func AESDecrypt(key, text []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+ if len(text) < aes.BlockSize {
+ return nil, errors.New("ciphertext too short")
+ }
+ iv := text[:aes.BlockSize]
+ text = text[aes.BlockSize:]
+ cfb := cipher.NewCFBDecrypter(block, iv)
+ cfb.XORKeyStream(text, text)
+ data, err := base64.StdEncoding.DecodeString(string(text))
+ if err != nil {
+ return nil, err
+ }
+ return data, 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()
+}
diff --git a/vendor/github.com/Unknwon/com/time.go b/vendor/github.com/Unknwon/com/time.go
new file mode 100644
index 0000000000..dd1cdbcf2a
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/time.go
@@ -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)
+}
diff --git a/vendor/github.com/Unknwon/com/url.go b/vendor/github.com/Unknwon/com/url.go
new file mode 100644
index 0000000000..b0b7c0e12b
--- /dev/null
+++ b/vendor/github.com/Unknwon/com/url.go
@@ -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
+}