package handlers import ( "fmt" "os" "path/filepath" "regexp" "strings" ) var numberSuffixRegex = regexp.MustCompile(` \(\d+\)$`) // GetUniquePath checks if a file or folder exists at the given baseDir with the given name. // If it does, it systematically appends " (1)", " (2)", etc., until it finds an available name. // It returns the unique filename. func GetUniquePath(baseDir, name string) string { ext := filepath.Ext(name) base := name[:len(name)-len(ext)] finalPath := filepath.Join(baseDir, name) if _, err := os.Stat(finalPath); os.IsNotExist(err) { return name } base = numberSuffixRegex.ReplaceAllString(base, "") for i := 1; ; i++ { newName := fmt.Sprintf("%s (%d)%s", base, i, ext) finalPath = filepath.Join(baseDir, newName) if _, err := os.Stat(finalPath); os.IsNotExist(err) { return newName } } } // resolveSafe safely resolves a requested path against a root directory, // ensuring the result is completely contained within the root. // Returns the absolute clean path or an error if traversal is detected. func resolveSafe(rootDir, reqPath string) (string, error) { cleanRoot := filepath.Clean(rootDir) // Pre-check for typical traversal patterns to be safe cleanReq := filepath.Clean(filepath.FromSlash(reqPath)) if strings.HasPrefix(cleanReq, "..") || strings.HasPrefix(cleanReq, "/") || strings.HasPrefix(cleanReq, "\\") { return "", fmt.Errorf("invalid path: contains traversal patterns") } absPath := filepath.Join(cleanRoot, cleanReq) // Ensure the resulting path starts with the root directory + separator // (or is exactly the root directory) if !strings.HasPrefix(absPath, cleanRoot+string(filepath.Separator)) && absPath != cleanRoot { return "", fmt.Errorf("path traversal attempt detected") } return absPath, nil }