2026-04-27 18:01:02 +03:00
|
|
|
package helpers
|
2026-04-27 17:49:19 +03:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
2026-04-27 18:01:02 +03:00
|
|
|
func SafeFilename(name string) (string, bool) {
|
2026-04-27 17:49:19 +03:00
|
|
|
filename := filepath.Base(name)
|
|
|
|
|
filename = strings.TrimSpace(filename)
|
|
|
|
|
return filename, filename != "" && filename != "." && filename != string(filepath.Separator)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 18:01:02 +03:00
|
|
|
func SafeChildPath(parent string, filename string) (string, bool) {
|
|
|
|
|
path := filepath.Join(parent, filename)
|
|
|
|
|
return path, strings.HasPrefix(path, parent+string(filepath.Separator))
|
2026-04-27 17:49:19 +03:00
|
|
|
}
|
|
|
|
|
|
2026-04-27 18:01:02 +03:00
|
|
|
func UniqueFilename(directory string, filename string) string {
|
2026-04-27 17:49:19 +03:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 18:01:02 +03:00
|
|
|
func UniqueNameInBatch(filename string, usedNames map[string]int) string {
|
2026-04-27 17:49:19 +03:00
|
|
|
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
|
|
|
|
|
}
|