package helpers import ( "os" "path/filepath" "strconv" "strings" ) func SafeFilename(name string) (string, bool) { filename := filepath.Base(name) filename = strings.TrimSpace(filename) return filename, filename != "" && filename != "." && filename != string(filepath.Separator) } func SafeChildPath(parent string, filename string) (string, bool) { parent = filepath.Clean(parent) filename = strings.TrimSpace(filename) if parent == "" || filename == "" || filepath.IsAbs(filename) { return "", false } path := filepath.Clean(filepath.Join(parent, filename)) relative, err := filepath.Rel(parent, path) if err != nil || relative == "." || strings.HasPrefix(relative, ".."+string(filepath.Separator)) || relative == ".." { return "", false } return path, true } func UniqueFilename(directory string, filename string) string { if _, err := os.Stat(filepath.Join(directory, filename)); os.IsNotExist(err) { return filename } extension := filepath.Ext(filename) base := strings.TrimSuffix(filename, extension) for count := 2; ; count++ { candidate := base + "-" + strconv.Itoa(count) + extension if _, err := os.Stat(filepath.Join(directory, candidate)); os.IsNotExist(err) { return candidate } } } func UniqueNameInBatch(filename string, usedNames map[string]int) string { count := usedNames[filename] usedNames[filename] = count + 1 if count == 0 { return filename } extension := filepath.Ext(filename) base := strings.TrimSuffix(filename, extension) return base + "-" + strconv.Itoa(count+1) + extension }