208 lines
4.7 KiB
Go
208 lines
4.7 KiB
Go
package utils
|
|
|
|
import (
|
|
cryptoRand "crypto/rand"
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"github.com/fossyy/filekeeper/app"
|
|
mathRand "math/rand"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
"unicode"
|
|
|
|
"github.com/joho/godotenv"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
type Env struct {
|
|
value map[string]string
|
|
mu sync.Mutex
|
|
}
|
|
|
|
var env *Env
|
|
|
|
func init() {
|
|
env = &Env{value: map[string]string{}}
|
|
}
|
|
|
|
func ClientIP(request *http.Request) string {
|
|
ip := request.Header.Get("Cf-Connecting-IP")
|
|
if ip != "" {
|
|
return ip
|
|
}
|
|
ip = request.Header.Get("X-Real-IP")
|
|
if ip == "" {
|
|
ip = request.Header.Get("X-Forwarded-For")
|
|
if ip == "" {
|
|
ip = request.RemoteAddr
|
|
}
|
|
}
|
|
|
|
if strings.Contains(ip, ",") {
|
|
ips := strings.Split(ip, ",")
|
|
ip = strings.TrimSpace(ips[0])
|
|
}
|
|
|
|
if strings.Contains(ip, ":") {
|
|
ips := strings.Split(ip, ":")
|
|
ip = ips[0]
|
|
}
|
|
|
|
return ip
|
|
}
|
|
|
|
func HashPassword(password string) (string, error) {
|
|
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
return string(bytes), err
|
|
}
|
|
|
|
func CheckPasswordHash(password, hash string) bool {
|
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
|
return err == nil
|
|
}
|
|
|
|
func ValidatePassword(password string) bool {
|
|
if len(password) < 8 {
|
|
return false
|
|
}
|
|
|
|
var (
|
|
hasNumber bool
|
|
hasUppercase bool
|
|
)
|
|
|
|
for _, char := range password {
|
|
switch {
|
|
case unicode.IsNumber(char):
|
|
hasNumber = true
|
|
case unicode.IsUpper(char):
|
|
hasUppercase = true
|
|
}
|
|
}
|
|
|
|
return hasNumber && hasUppercase
|
|
}
|
|
|
|
func ConvertFileSize(byte uint64) string {
|
|
if byte < 1024 {
|
|
return fmt.Sprintf("%d B", byte)
|
|
} else if byte < 1024*1024 {
|
|
return fmt.Sprintf("%d KB", byte/1024)
|
|
} else if byte < 1024*1024*1024 {
|
|
return fmt.Sprintf("%d MB", byte/(1024*1024))
|
|
} else {
|
|
return fmt.Sprintf("%d GB", byte/(1024*1024*1024))
|
|
}
|
|
}
|
|
|
|
func Getenv(key string) string {
|
|
env.mu.Lock()
|
|
defer env.mu.Unlock()
|
|
if val, ok := env.value[key]; ok {
|
|
return val
|
|
}
|
|
|
|
if os.Getenv("HOSTNAME") == "" {
|
|
err := godotenv.Load(".env")
|
|
if err != nil {
|
|
app.Server.Logger.Error("Error loading .env file: %s", err)
|
|
}
|
|
}
|
|
|
|
val := os.Getenv(key)
|
|
env.value[key] = val
|
|
|
|
return val
|
|
}
|
|
|
|
func GenerateRandomString(length int) string {
|
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
seededRand := mathRand.New(mathRand.NewSource(time.Now().UnixNano() + int64(mathRand.Intn(9999))))
|
|
var result strings.Builder
|
|
for i := 0; i < length; i++ {
|
|
randomIndex := seededRand.Intn(len(charset))
|
|
result.WriteString(string(charset[randomIndex]))
|
|
}
|
|
return result.String()
|
|
}
|
|
|
|
func GenerateCSRFToken() (string, error) {
|
|
tokenBytes := make([]byte, 32)
|
|
_, err := cryptoRand.Read(tokenBytes)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
hash := sha1.New()
|
|
hash.Write(tokenBytes)
|
|
hashedToken := hash.Sum(nil)
|
|
|
|
csrfToken := base64.URLEncoding.EncodeToString(hashedToken)
|
|
|
|
return csrfToken, nil
|
|
}
|
|
|
|
func ParseUserAgent(userAgent string) (map[string]string, map[string]string) {
|
|
browserInfo := make(map[string]string)
|
|
osInfo := make(map[string]string)
|
|
if strings.Contains(userAgent, "Firefox") {
|
|
browserInfo["browser"] = "Firefox"
|
|
parts := strings.Split(userAgent, "Firefox/")
|
|
if len(parts) > 1 {
|
|
version := strings.Split(parts[1], " ")[0]
|
|
browserInfo["version"] = version
|
|
}
|
|
} else if strings.Contains(userAgent, "Chrome") {
|
|
browserInfo["browser"] = "Chrome"
|
|
parts := strings.Split(userAgent, "Chrome/")
|
|
if len(parts) > 1 {
|
|
version := strings.Split(parts[1], " ")[0]
|
|
browserInfo["version"] = version
|
|
}
|
|
} else {
|
|
browserInfo["browser"] = "Unknown"
|
|
browserInfo["version"] = "Unknown"
|
|
}
|
|
|
|
if strings.Contains(userAgent, "Windows") {
|
|
osInfo["os"] = "Windows"
|
|
parts := strings.Split(userAgent, "Windows ")
|
|
if len(parts) > 1 {
|
|
version := strings.Split(parts[1], ";")[0]
|
|
osInfo["version"] = version
|
|
}
|
|
} else if strings.Contains(userAgent, "Macintosh") {
|
|
osInfo["os"] = "Mac OS"
|
|
parts := strings.Split(userAgent, "Mac OS X ")
|
|
if len(parts) > 1 {
|
|
version := strings.Split(parts[1], ";")[0]
|
|
osInfo["version"] = version
|
|
}
|
|
} else if strings.Contains(userAgent, "Linux") {
|
|
osInfo["os"] = "Linux"
|
|
osInfo["version"] = "Unknown"
|
|
} else if strings.Contains(userAgent, "Android") {
|
|
osInfo["os"] = "Android"
|
|
parts := strings.Split(userAgent, "Android ")
|
|
if len(parts) > 1 {
|
|
version := strings.Split(parts[1], ";")[0]
|
|
osInfo["version"] = version
|
|
}
|
|
} else if strings.Contains(userAgent, "iPhone") || strings.Contains(userAgent, "iPad") || strings.Contains(userAgent, "iPod") {
|
|
osInfo["os"] = "iOS"
|
|
parts := strings.Split(userAgent, "OS ")
|
|
if len(parts) > 1 {
|
|
version := strings.Split(parts[1], " ")[0]
|
|
osInfo["version"] = version
|
|
}
|
|
} else {
|
|
osInfo["os"] = "Unknown"
|
|
osInfo["version"] = "Unknown"
|
|
}
|
|
|
|
return browserInfo, osInfo
|
|
}
|