mirror of https://github.com/Xhofe/alist
211 lines
4.6 KiB
Go
211 lines
4.6 KiB
Go
package _189pc
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/aes"
|
|
"crypto/hmac"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha1"
|
|
"crypto/x509"
|
|
"encoding/hex"
|
|
"encoding/pem"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"math"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/alist-org/alist/v3/pkg/utils/random"
|
|
)
|
|
|
|
func clientSuffix() map[string]string {
|
|
rand := random.Rand
|
|
return map[string]string{
|
|
"clientType": PC,
|
|
"version": VERSION,
|
|
"channelId": CHANNEL_ID,
|
|
"rand": fmt.Sprintf("%d_%d", rand.Int63n(1e5), rand.Int63n(1e10)),
|
|
}
|
|
}
|
|
|
|
// 带params的SignatureOfHmac HMAC签名
|
|
func signatureOfHmac(sessionSecret, sessionKey, operate, fullUrl, dateOfGmt, param string) string {
|
|
urlpath := regexp.MustCompile(`://[^/]+((/[^/\s?#]+)*)`).FindStringSubmatch(fullUrl)[1]
|
|
mac := hmac.New(sha1.New, []byte(sessionSecret))
|
|
data := fmt.Sprintf("SessionKey=%s&Operate=%s&RequestURI=%s&Date=%s", sessionKey, operate, urlpath, dateOfGmt)
|
|
if param != "" {
|
|
data += fmt.Sprintf("¶ms=%s", param)
|
|
}
|
|
mac.Write([]byte(data))
|
|
return strings.ToUpper(hex.EncodeToString(mac.Sum(nil)))
|
|
}
|
|
|
|
// RAS 加密用户名密码
|
|
func RsaEncrypt(publicKey, origData string) string {
|
|
block, _ := pem.Decode([]byte(publicKey))
|
|
pubInterface, _ := x509.ParsePKIXPublicKey(block.Bytes)
|
|
data, _ := rsa.EncryptPKCS1v15(rand.Reader, pubInterface.(*rsa.PublicKey), []byte(origData))
|
|
return strings.ToUpper(hex.EncodeToString(data))
|
|
}
|
|
|
|
// aes 加密params
|
|
func AesECBEncrypt(data, key string) string {
|
|
block, _ := aes.NewCipher([]byte(key))
|
|
paddingData := PKCS7Padding([]byte(data), block.BlockSize())
|
|
decrypted := make([]byte, len(paddingData))
|
|
size := block.BlockSize()
|
|
for src, dst := paddingData, decrypted; len(src) > 0; src, dst = src[size:], dst[size:] {
|
|
block.Encrypt(dst[:size], src[:size])
|
|
}
|
|
return strings.ToUpper(hex.EncodeToString(decrypted))
|
|
}
|
|
|
|
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
|
|
padding := blockSize - len(ciphertext)%blockSize
|
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
return append(ciphertext, padtext...)
|
|
}
|
|
|
|
// 获取http规范的时间
|
|
func getHttpDateStr() string {
|
|
return time.Now().UTC().Format(http.TimeFormat)
|
|
}
|
|
|
|
// 时间戳
|
|
func timestamp() int64 {
|
|
return time.Now().UTC().UnixNano() / 1e6
|
|
}
|
|
|
|
func MustParseTime(str string) *time.Time {
|
|
lastOpTime, _ := time.ParseInLocation("2006-01-02 15:04:05 -07", str+" +08", time.Local)
|
|
return &lastOpTime
|
|
}
|
|
|
|
type Time time.Time
|
|
|
|
func (t *Time) UnmarshalJSON(b []byte) error { return t.Unmarshal(b) }
|
|
func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
|
|
b, err := e.Token()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if b, ok := b.(xml.CharData); ok {
|
|
if err = t.Unmarshal(b); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return e.Skip()
|
|
}
|
|
func (t *Time) Unmarshal(b []byte) error {
|
|
bs := strings.Trim(string(b), "\"")
|
|
var v time.Time
|
|
var err error
|
|
for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 15:04:05 PM -07"} {
|
|
v, err = time.ParseInLocation(f, bs+" +08", time.Local)
|
|
if err == nil {
|
|
break
|
|
}
|
|
}
|
|
*t = Time(v)
|
|
return err
|
|
}
|
|
|
|
type String string
|
|
|
|
func (t *String) UnmarshalJSON(b []byte) error { return t.Unmarshal(b) }
|
|
func (t *String) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
|
|
b, err := e.Token()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if b, ok := b.(xml.CharData); ok {
|
|
if err = t.Unmarshal(b); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return e.Skip()
|
|
}
|
|
func (s *String) Unmarshal(b []byte) error {
|
|
*s = String(bytes.Trim(b, "\""))
|
|
return nil
|
|
}
|
|
|
|
func toFamilyOrderBy(o string) string {
|
|
switch o {
|
|
case "filename":
|
|
return "1"
|
|
case "filesize":
|
|
return "2"
|
|
case "lastOpTime":
|
|
return "3"
|
|
default:
|
|
return "1"
|
|
}
|
|
}
|
|
|
|
func toDesc(o string) string {
|
|
switch o {
|
|
case "desc":
|
|
return "true"
|
|
case "asc":
|
|
fallthrough
|
|
default:
|
|
return "false"
|
|
}
|
|
}
|
|
|
|
func ParseHttpHeader(str string) map[string]string {
|
|
header := make(map[string]string)
|
|
for _, value := range strings.Split(str, "&") {
|
|
if k, v, found := strings.Cut(value, "="); found {
|
|
header[k] = v
|
|
}
|
|
}
|
|
return header
|
|
}
|
|
|
|
func MustString(str string, err error) string {
|
|
return str
|
|
}
|
|
|
|
func BoolToNumber(b bool) int {
|
|
if b {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// 计算分片大小
|
|
// 对分片数量有限制
|
|
// 10MIB 20 MIB 999片
|
|
// 50MIB 60MIB 70MIB 80MIB ∞MIB 1999片
|
|
func partSize(size int64) int64 {
|
|
const DEFAULT = 1024 * 1024 * 10 // 10MIB
|
|
if size > DEFAULT*2*999 {
|
|
return int64(math.Max(math.Ceil((float64(size)/1999) /*=单个切片大小*/ /float64(DEFAULT)) /*=倍率*/, 5) * DEFAULT)
|
|
}
|
|
if size > DEFAULT*999 {
|
|
return DEFAULT * 2 // 20MIB
|
|
}
|
|
return DEFAULT
|
|
}
|
|
|
|
func isBool(bs ...bool) bool {
|
|
for _, b := range bs {
|
|
if b {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func IF[V any](o bool, t V, f V) V {
|
|
if o {
|
|
return t
|
|
}
|
|
return f
|
|
}
|