mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
5.4 KiB
253 lines
5.4 KiB
// 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() |
|
}
|
|
|