45 lines
1.3 KiB
Go

// backend/internal/naming.go
package internal
import (
"fmt"
"path/filepath"
"regexp"
"strings"
"time"
)
var (
descMax = 64
allowedDesc = regexp.MustCompile(`[^A-Za-z0-9 _-]`) // to be replaced by `_`
dateOnly = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`) // UI sends YYYY-MM-DD
finalNameValidate = regexp.MustCompile(`^\d{4}\.\d{2}\.\d{2}\.[A-Za-z0-9_-]{1,64}\.[A-Za-z0-9]{1,8}$`)
)
func SanitizeDesc(in string) string {
s := strings.TrimSpace(in)
if s == "" { s = "upload" }
s = allowedDesc.ReplaceAllString(s, "_")
s = strings.Join(strings.Fields(s), "_") // collapse whitespace
if len(s) > descMax { s = s[:descMax] }
return s
}
func ComposeFinalName(dateStr, desc, origFilename string) (string, error) {
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(origFilename), "."))
if ext == "" { ext = "bin" }
var t time.Time
var err error
if dateOnly.MatchString(dateStr) {
t, err = time.Parse("2006-01-02", dateStr)
} else {
t = time.Now()
}
if err != nil { return "", fmt.Errorf("bad date") }
final := fmt.Sprintf("%04d.%02d.%02d.%s.%s", t.Year(), int(t.Month()), t.Day(), SanitizeDesc(desc), ext)
if !finalNameValidate.MatchString(final) { return "", fmt.Errorf("invalid final name") }
return final, nil
}