package common import ( "crypto/md5" "crypto/rand" "encoding/hex" "fmt" "math/big" "net" "os" "path" "sort" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/utils/cmd" ) var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") func RandStr(n int) string { b := make([]rune, n) max := big.NewInt(int64(len(letters))) for i := range b { num, err := rand.Int(rand.Reader, max) if err != nil { return "" } b[i] = letters[num.Int64()] } return string(b) } func RandStrAndNum(n int) string { const charset = "abcdefghijklmnopqrstuvwxyz0123456789" b := make([]byte, n) max := big.NewInt(int64(len(charset))) for i := range b { num, err := rand.Int(rand.Reader, max) if err != nil { return "" } b[i] = charset[num.Int64()] } return string(b) } func Md5(val string) string { hash := md5.New() hash.Write([]byte(val)) return hex.EncodeToString(hash.Sum(nil)) } func ScanPort(port int) bool { ln, err := net.Listen("tcp", ":"+strconv.Itoa(port)) if err != nil { return true } defer func() { _ = ln.Close() }() return false } func CheckPort(host string, port string, timeout time.Duration) bool { target := net.JoinHostPort(host, port) conn, err := net.DialTimeout("tcp", target, timeout) if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { return false } return strings.Contains(err.Error(), "connection refused") } defer func() { _ = conn.Close() }() return true } func ComparePanelVersion(version1, version2 string) bool { if version1 == version2 { return false } version1s := SplitStr(version1, ".", "-") version2s := SplitStr(version2, ".", "-") if len(version2s) > len(version1s) { for i := 0; i < len(version2s)-len(version1s); i++ { version1s = append(version1s, "0") } } if len(version1s) > len(version2s) { for i := 0; i < len(version1s)-len(version2s); i++ { version2s = append(version2s, "0") } } n := min(len(version1s), len(version2s)) for i := 0; i < n; i++ { if version1s[i] == version2s[i] { continue } else { v1, err1 := strconv.Atoi(version1s[i]) if err1 != nil { return version1s[i] > version2s[i] } v2, err2 := strconv.Atoi(version2s[i]) if err2 != nil { return version1s[i] > version2s[i] } return v1 > v2 } } return true } func SplitStr(str string, spi ...string) []string { lists := []string{str} var results []string for _, s := range spi { results = []string{} for _, list := range lists { results = append(results, strings.Split(list, s)...) } lists = results } return results } func UniqueUints(items []uint) []uint { result := make([]uint, 0, len(items)) seen := make(map[uint]struct{}, len(items)) for _, item := range items { if item == 0 { continue } if _, ok := seen[item]; ok { continue } seen[item] = struct{}{} result = append(result, item) } sort.Slice(result, func(i, j int) bool { return result[i] < result[j] }) return result } func LoadArch() (string, error) { std, err := cmd.NewCommandMgr().RunWithStdout("uname", "-a") if err != nil { return "", fmt.Errorf("std: %s, err: %s", std, err.Error()) } return LoadArchWithStdout(std) } func LoadArchWithStdout(std string) (string, error) { if strings.Contains(std, "x86_64") { return "amd64", nil } if strings.Contains(std, "arm64") || strings.Contains(std, "aarch64") { return "arm64", nil } if strings.Contains(std, "armv7l") { return "armv7", nil } if strings.Contains(std, "ppc64le") { return "ppc64le", nil } if strings.Contains(std, "s390x") { return "s390x", nil } if strings.Contains(std, "riscv64") { return "riscv64", nil } return "", fmt.Errorf("unsupported such arch: %s", std) } func Clean(str []byte) { for i := 0; i < len(str); i++ { str[i] = 0 } } func CreateDirWhenNotExist(isDir bool, pathItem string) (string, error) { checkPath := pathItem if !isDir { checkPath = path.Dir(pathItem) } if _, err := os.Stat(checkPath); err != nil && os.IsNotExist(err) { if err = os.MkdirAll(checkPath, os.ModePerm); err != nil { global.LOG.Errorf("mkdir %s failed, err: %v", checkPath, err) return pathItem, err } } return pathItem, nil } func GetLang(c *gin.Context) string { lang := c.GetHeader("Accept-Language") if lang == "" { lang = "en" } return lang } func CheckIpInCidr(cidr, checkIP string) bool { ip, ipNet, err := net.ParseCIDR(cidr) if err != nil { global.LOG.Errorf("parse CIDR %s failed, err: %v", cidr, err) return false } for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) { if ip.String() == checkIP { return true } } return false } func incIP(ip net.IP) { for j := len(ip) - 1; j >= 0; j-- { ip[j]++ if ip[j] > 0 { break } } } func HandleIPList(content string) ([]string, error) { ipList := strings.Split(content, "\n") var res []string for _, ip := range ipList { ip = strings.TrimSpace(ip) if ip == "" { continue } if net.ParseIP(ip) != nil { res = append(res, ip) continue } if _, _, err := net.ParseCIDR(ip); err != nil { return nil, err } res = append(res, ip) } return res, nil } func GetRealClientIP(c *gin.Context) string { addr := c.Request.RemoteAddr if ip, _, err := net.SplitHostPort(addr); err == nil { return ip } return addr } func IsPrivateIP(ipStr string) bool { ip := net.ParseIP(ipStr) if ip == nil { return false } return ip.IsPrivate() || ip.IsLoopback() }