feat: Windows-Kompatibilität
- WorkspaceHelper: Zentrale Hilfsmethoden (IsWindows, TempDir, IsSubPathOf, GetRelativePath, ShellExecutable, ShellArguments) - ToolService: execute nutzt cmd.exe auf Windows, GetRelativePath mit Forward-Slashes, IsSubPathOf für case-insensitive Pfadprüfung - SessionEndpoint: /tmp → Path.GetTempPath(), bash → cmd.exe, Fire-and-forget via .bat statt systemd-run auf Windows - ChatService: /tmp → WorkspaceHelper.TempDir - MemoryService: IsSubPathOf + GetRelativePath - WorkspaceEndpoint: HandleBrowse zeigt Laufwerke auf Windows, IsSubPathOf statt StartsWith - InfoEndpoint: gott.exe auf Windows, isWindows-Flag in API-Response - Frontend: File-Explorer mit Laufwerks-Navigation auf Windows
This commit is contained in:
1 parent
79899a6981
commit
5d090e160b
9 files changed
+155
-61
No files matched your search
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Gott.Services;
|
||||
|
||||
namespace Gott.Endpoints;
|
||||
|
||||
@@ -83,7 +84,7 @@ public static class WorkspaceEndpoint
|
||||
|
||||
var userId = ctx.GetUserId();
|
||||
var user = await db.GetUser(userId);
|
||||
var resolved = Gott.Services.WorkspaceHelper.ResolveWorkspace(session, user);
|
||||
var resolved = WorkspaceHelper.ResolveWorkspace(session, user);
|
||||
if (string.IsNullOrEmpty(resolved))
|
||||
{
|
||||
ctx.Response.StatusCode = 400;
|
||||
@@ -125,7 +126,7 @@ public static class WorkspaceEndpoint
|
||||
var subPath = ctx.Request.Query["path"].FirstOrDefault() ?? "";
|
||||
var targetPath = Path.GetFullPath(Path.Combine(basePath, subPath));
|
||||
|
||||
if (!targetPath.StartsWith(basePath))
|
||||
if (!WorkspaceHelper.IsSubPathOf(targetPath, basePath))
|
||||
{
|
||||
ctx.Response.StatusCode = 403;
|
||||
return;
|
||||
@@ -144,7 +145,7 @@ public static class WorkspaceEndpoint
|
||||
{
|
||||
var name = Path.GetFileName(dir);
|
||||
if (IgnoredDirs.Contains(name)) continue;
|
||||
var relPath = Path.GetRelativePath(basePath, dir).Replace('\\', '/');
|
||||
var relPath = WorkspaceHelper.GetRelativePath(basePath, dir);
|
||||
entries.Add(new { name, path = relPath, type = "dir" });
|
||||
}
|
||||
|
||||
@@ -152,7 +153,7 @@ public static class WorkspaceEndpoint
|
||||
{
|
||||
var name = Path.GetFileName(file);
|
||||
var ext = Path.GetExtension(file);
|
||||
var relPath = Path.GetRelativePath(basePath, file).Replace('\\', '/');
|
||||
var relPath = WorkspaceHelper.GetRelativePath(basePath, file);
|
||||
var size = new FileInfo(file).Length;
|
||||
var isText = TextExtensions.Contains(ext) || IsLikelyTextFile(name);
|
||||
entries.Add(new { name, path = relPath, type = "file", ext, size, isText });
|
||||
@@ -173,7 +174,7 @@ public static class WorkspaceEndpoint
|
||||
}
|
||||
|
||||
var targetPath = Path.GetFullPath(Path.Combine(basePath, filePath));
|
||||
if (!targetPath.StartsWith(basePath))
|
||||
if (!WorkspaceHelper.IsSubPathOf(targetPath, basePath))
|
||||
{
|
||||
ctx.Response.StatusCode = 403;
|
||||
return;
|
||||
@@ -218,7 +219,7 @@ public static class WorkspaceEndpoint
|
||||
}
|
||||
|
||||
var targetPath = Path.GetFullPath(Path.Combine(basePath, filePath));
|
||||
if (!targetPath.StartsWith(basePath))
|
||||
if (!WorkspaceHelper.IsSubPathOf(targetPath, basePath))
|
||||
{
|
||||
ctx.Response.StatusCode = 403;
|
||||
return;
|
||||
@@ -271,7 +272,7 @@ public static class WorkspaceEndpoint
|
||||
}
|
||||
|
||||
var targetPath = Path.GetFullPath(Path.Combine(basePath, dirPath));
|
||||
if (!targetPath.StartsWith(basePath))
|
||||
if (!WorkspaceHelper.IsSubPathOf(targetPath, basePath))
|
||||
{
|
||||
ctx.Response.StatusCode = 403;
|
||||
return;
|
||||
@@ -287,7 +288,7 @@ public static class WorkspaceEndpoint
|
||||
Directory.CreateDirectory(targetPath);
|
||||
await ctx.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
path = Path.GetRelativePath(basePath, targetPath).Replace('\\', '/'),
|
||||
path = WorkspaceHelper.GetRelativePath(basePath, targetPath),
|
||||
created = true
|
||||
});
|
||||
}
|
||||
@@ -296,7 +297,18 @@ public static class WorkspaceEndpoint
|
||||
|
||||
private static async Task HandleBrowse(HttpContext ctx)
|
||||
{
|
||||
var path = ctx.Request.Query["path"].FirstOrDefault() ?? "/";
|
||||
var path = ctx.Request.Query["path"].FirstOrDefault() ?? (WorkspaceHelper.IsWindows ? "" : "/");
|
||||
|
||||
// Windows: Leerer Pfad oder Root → Laufwerke anzeigen
|
||||
if (WorkspaceHelper.IsWindows && string.IsNullOrEmpty(path))
|
||||
{
|
||||
var drives = System.IO.DriveInfo.GetDrives()
|
||||
.Where(d => d.IsReady)
|
||||
.Select(d => new { name = d.Name.TrimEnd('\\'), path = d.Name.Replace('\\', '/'), type = "dir" })
|
||||
.ToList<object>();
|
||||
await ctx.Response.WriteAsJsonAsync(new { current = "", entries = drives });
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPath = Path.GetFullPath(path);
|
||||
if (!Directory.Exists(targetPath))
|
||||
@@ -368,7 +380,7 @@ public static class WorkspaceEndpoint
|
||||
if (basePath == null) return;
|
||||
|
||||
var targetPath = Path.GetFullPath(Path.Combine(basePath, filePath));
|
||||
if (!targetPath.StartsWith(basePath))
|
||||
if (!WorkspaceHelper.IsSubPathOf(targetPath, basePath))
|
||||
{
|
||||
ctx.Response.StatusCode = 403;
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user