mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 08:57:12 +00:00
49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
package securityutil
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// HashedStorageName derives an opaque, fixed-width storage filename stem from an external identifier.
|
|
func HashedStorageName(id string) string {
|
|
sum := sha256.Sum256([]byte(id))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
// NormalizeStorageDir trims and canonicalizes an already-owned storage directory path.
|
|
func NormalizeStorageDir(dir string) (string, error) {
|
|
trimmedDir := strings.TrimSpace(dir)
|
|
if trimmedDir == "" {
|
|
return "", fmt.Errorf("storage directory is required")
|
|
}
|
|
|
|
return filepath.Clean(trimmedDir), nil
|
|
}
|
|
|
|
// JoinStorageLeaf joins an already-owned storage directory with a validated leaf filename.
|
|
func JoinStorageLeaf(dir, leaf string) (string, error) {
|
|
normalizedDir, err := NormalizeStorageDir(dir)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
name := strings.TrimSpace(leaf)
|
|
if name == "" {
|
|
return "", fmt.Errorf("storage leaf is required")
|
|
}
|
|
if name == "." || name == ".." {
|
|
return "", fmt.Errorf("storage leaf must not be '.' or '..'")
|
|
}
|
|
if filepath.Base(name) != name {
|
|
return "", fmt.Errorf("storage leaf must not contain path separators")
|
|
}
|
|
if strings.ContainsAny(name, `/\`) {
|
|
return "", fmt.Errorf("storage leaf must not contain path separators")
|
|
}
|
|
|
|
return filepath.Join(normalizedDir, name), nil
|
|
}
|