186 lines
3.3 KiB
Go
186 lines
3.3 KiB
Go
package util
|
|
|
|
import (
|
|
"bytes"
|
|
srand "crypto/rand"
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/rand"
|
|
"net/http"
|
|
"net/url"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
const dictionary = "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
|
|
//CreateRandomString create random string
|
|
func CreateRandomString() string {
|
|
b := make([]byte, 32)
|
|
l := len(dictionary)
|
|
|
|
_, err := srand.Read(b)
|
|
|
|
if err != nil {
|
|
// fail back to insecure rand
|
|
rand.Seed(time.Now().UnixNano())
|
|
for i := range b {
|
|
b[i] = dictionary[rand.Int()%l]
|
|
}
|
|
} else {
|
|
for i, v := range b {
|
|
b[i] = dictionary[v%byte(l)]
|
|
}
|
|
}
|
|
|
|
return string(b)
|
|
}
|
|
|
|
// Encode encodes the values into ``URL encoded'' form
|
|
// ("acl&bar=baz&foo=quux") sorted by key.
|
|
func Encode(v url.Values) string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
var buf bytes.Buffer
|
|
keys := make([]string, 0, len(v))
|
|
for k := range v {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
vs := v[k]
|
|
prefix := url.QueryEscape(k)
|
|
for _, v := range vs {
|
|
if buf.Len() > 0 {
|
|
buf.WriteByte('&')
|
|
}
|
|
buf.WriteString(prefix)
|
|
if v != "" {
|
|
buf.WriteString("=")
|
|
buf.WriteString(url.QueryEscape(v))
|
|
}
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// Like Encode, but key and value are not escaped
|
|
func EncodeWithoutEscape(v url.Values) string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
var buf bytes.Buffer
|
|
keys := make([]string, 0, len(v))
|
|
for k := range v {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
vs := v[k]
|
|
prefix := k
|
|
for _, v := range vs {
|
|
if buf.Len() > 0 {
|
|
buf.WriteByte('&')
|
|
}
|
|
buf.WriteString(prefix)
|
|
if v != "" {
|
|
buf.WriteString("=")
|
|
buf.WriteString(v)
|
|
}
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func GetGMTime() string {
|
|
return time.Now().UTC().Format(http.TimeFormat)
|
|
}
|
|
|
|
//
|
|
|
|
func randUint32() uint32 {
|
|
return randUint32Slice(1)[0]
|
|
}
|
|
|
|
func randUint32Slice(c int) []uint32 {
|
|
b := make([]byte, c*4)
|
|
|
|
_, err := srand.Read(b)
|
|
|
|
if err != nil {
|
|
// fail back to insecure rand
|
|
rand.Seed(time.Now().UnixNano())
|
|
for i := range b {
|
|
b[i] = byte(rand.Int())
|
|
}
|
|
}
|
|
|
|
n := make([]uint32, c)
|
|
|
|
for i := range n {
|
|
n[i] = binary.BigEndian.Uint32(b[i*4 : i*4+4])
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
func toByte(n uint32, st, ed byte) byte {
|
|
return byte(n%uint32(ed-st+1) + uint32(st))
|
|
}
|
|
|
|
func toDigit(n uint32) byte {
|
|
return toByte(n, '0', '9')
|
|
}
|
|
|
|
func toLowerLetter(n uint32) byte {
|
|
return toByte(n, 'a', 'z')
|
|
}
|
|
|
|
func toUpperLetter(n uint32) byte {
|
|
return toByte(n, 'A', 'Z')
|
|
}
|
|
|
|
type convFunc func(uint32) byte
|
|
|
|
var convFuncs = []convFunc{toDigit, toLowerLetter, toUpperLetter}
|
|
|
|
// tools for generating a random ECS instance password
|
|
// from 8 to 30 char MUST contain digit upper, case letter and upper case letter
|
|
// http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance
|
|
func GenerateRandomECSPassword() string {
|
|
|
|
// [8, 30]
|
|
l := int(randUint32()%23 + 8)
|
|
|
|
n := randUint32Slice(l)
|
|
|
|
b := make([]byte, l)
|
|
|
|
b[0] = toDigit(n[0])
|
|
b[1] = toLowerLetter(n[1])
|
|
b[2] = toUpperLetter(n[2])
|
|
|
|
for i := 3; i < l; i++ {
|
|
b[i] = convFuncs[n[i]%3](n[i])
|
|
}
|
|
|
|
s := make([]byte, l)
|
|
perm := rand.Perm(l)
|
|
for i, v := range perm {
|
|
s[v] = b[i]
|
|
}
|
|
|
|
return string(s)
|
|
|
|
}
|
|
|
|
func PrettyJson(object interface{}) string {
|
|
b, err := json.MarshalIndent(object, "", " ")
|
|
if err != nil {
|
|
fmt.Printf("ERROR: PrettyJson, %v\n %s\n", err, b)
|
|
}
|
|
return string(b)
|
|
}
|