| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 | // 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 comimport (	"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 unicodefunc 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/xstringsfunc 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()}
 |