using System; using System.IO; using Gott.Models; namespace Gott.Services; public static class WorkspaceHelper { /// /// Löst den Workspace-Pfad einer Session auf. /// session.Workspace ist relativ zum user.DefaultPath. /// Gibt den absoluten Pfad zurück oder null wenn kein Workspace konfiguriert ist. /// public static string ResolveWorkspace(SessionRecord session, UserRecord user) { if (session == null || string.IsNullOrWhiteSpace(session.Workspace)) return null; var workspace = session.Workspace.Trim(); // Wenn der Workspace bereits ein absoluter Pfad ist (Legacy/Fallback) if (Path.IsPathRooted(workspace)) return Path.GetFullPath(workspace); // Relativer Pfad → mit DefaultPath des Users kombinieren var basePath = user?.DefaultPath?.Trim(); if (string.IsNullOrWhiteSpace(basePath)) return null; // Kein DefaultPath gesetzt → relativer Workspace kann nicht aufgelöst werden var resolved = Path.GetFullPath(Path.Combine(basePath, workspace)); // Sicherheit: darf nicht aus dem DefaultPath ausbrechen var normalizedBase = Path.GetFullPath(basePath); if (!resolved.StartsWith(normalizedBase + Path.DirectorySeparatorChar) && resolved != normalizedBase) return null; return resolved; } /// /// Validiert einen relativen Workspace-Pfad. /// Prüft auf Path-Traversal (.. etc.). /// Gibt den bereinigten Pfad zurück oder null bei ungültigem Pfad. /// public static string ValidateRelativeWorkspace(string workspace) { if (string.IsNullOrWhiteSpace(workspace)) return null; var trimmed = workspace.Trim().TrimStart('/').TrimEnd('/'); if (string.IsNullOrEmpty(trimmed)) return null; // Path-Traversal verhindern if (trimmed.Contains("..") || trimmed.Contains("~")) return null; // Keine absoluten Pfade erlauben if (Path.IsPathRooted(trimmed)) return null; return trimmed; } /// /// Konvertiert einen absoluten Workspace-Pfad in einen relativen Pfad zum DefaultPath. /// Wird beim Speichern verwendet, damit alte absolute Pfade in relative umgewandelt werden. /// public static string ToRelativeWorkspace(string absoluteWorkspace, string defaultPath) { if (string.IsNullOrWhiteSpace(absoluteWorkspace)) return null; if (string.IsNullOrWhiteSpace(defaultPath)) return absoluteWorkspace; // Kein DefaultPath → absoluten Pfad beibehalten (Legacy) var normalizedBase = Path.GetFullPath(defaultPath.Trim()); var normalizedWorkspace = Path.GetFullPath(absoluteWorkspace.Trim()); if (normalizedWorkspace.StartsWith(normalizedBase + Path.DirectorySeparatorChar)) return normalizedWorkspace.Substring(normalizedBase.Length + 1); if (normalizedWorkspace == normalizedBase) return ""; return absoluteWorkspace; // Außerhalb des DefaultPath → absoluten Pfad beibehalten (Legacy) } }