diff --git a/Moonlight/App/Helpers/Files/FtpFileAccess.cs b/Moonlight/App/Helpers/Files/FtpFileAccess.cs new file mode 100644 index 0000000..ec3e66c --- /dev/null +++ b/Moonlight/App/Helpers/Files/FtpFileAccess.cs @@ -0,0 +1,184 @@ +using System.Net; +using System.Text; +using FluentFTP; + +namespace Moonlight.App.Helpers.Files; + +public class FtpFileAccess : FileAccess +{ + private string FtpHost, FtpUser, FtpPassword; + private int FtpPort; + + private AsyncFtpClient Client; + + public FtpFileAccess(string ftpHost, int ftpPort, string ftpUser, string ftpPassword) + { + FtpHost = ftpHost; + FtpPort = ftpPort; + FtpUser = ftpUser; + FtpPassword = ftpPassword; + + Client = new AsyncFtpClient(FtpHost, FtpUser, FtpPassword, FtpPort); + } + + private async Task EnsureConnect() + { + if (!Client.IsConnected) + await Client.AutoConnect(); + } + + public override async Task Ls() + { + await EnsureConnect(); + + var x = new List(); + + foreach (FtpListItem item in await Client.GetListing(CurrentPath)) + { + long size = 0; + + if (item.Type == FtpObjectType.File) + { + size = await Client.GetFileSize(item.FullName); + } + + x.Add(new() + { + Name = item.Name, + Size = size, + IsFile = item.Type == FtpObjectType.File, + }); + } + + return x.ToArray(); + } + + public override Task Cd(string dir) + { + var x = Path.Combine(CurrentPath, dir).Replace("\\", "/") + "/"; + x = x.Replace("//", "/"); + CurrentPath = x; + + return Task.CompletedTask; + } + + public override Task Up() + { + CurrentPath = Path.GetFullPath(Path.Combine(CurrentPath, "..")).Replace("\\", "/").Replace("C:", ""); + return Task.CompletedTask; + } + + public override Task SetDir(string dir) + { + CurrentPath = dir; + return Task.CompletedTask; + } + + public override async Task Read(FileData fileData) + { + await EnsureConnect(); + + var s = new MemoryStream(); + await Client.DownloadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name); + var data = s.ToArray(); + s.Dispose(); + var str = Encoding.UTF8.GetString(data); + return str; + } + + public override async Task Write(FileData fileData, string content) + { + await EnsureConnect(); + + var s = new MemoryStream(); + s.Write(Encoding.UTF8.GetBytes(content)); + s.Position = 0; + await Client.UploadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name, FtpRemoteExists.Overwrite); + s.Dispose(); + } + + public override async Task Upload(string name, Stream dataStream, Action? progressUpdated = null) + { + await EnsureConnect(); + + IProgress progress = new Progress(x => + { + progressUpdated((int) x.Progress); + }); + await Client.UploadStream(dataStream, CurrentPath.TrimEnd('/') + "/" + name, FtpRemoteExists.Overwrite, false, progress); + dataStream.Dispose(); + } + + public override async Task MkDir(string name) + { + await EnsureConnect(); + + await Client.CreateDirectory(CurrentPath.TrimEnd('/') + "/" + name + "/"); + } + + public override Task Pwd() + { + return Task.FromResult(CurrentPath); + } + + public override async Task DownloadUrl(FileData fileData) + { + await EnsureConnect(); + + throw new NotImplementedException(); + } + + public override async Task DownloadStream(FileData fileData) + { + await EnsureConnect(); + + var s = new MemoryStream(); + await Client.DownloadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name); + return s; + } + + public override async Task Delete(FileData fileData) + { + await EnsureConnect(); + + if (fileData.IsFile) + await Client.DeleteFile(CurrentPath.TrimEnd('/') + "/" + fileData.Name); + else + await Client.DeleteDirectory(CurrentPath.TrimEnd('/') + "/" + fileData.Name); + } + + public override async Task Move(FileData fileData, string newPath) + { + await EnsureConnect(); + + if (fileData.IsFile) + await Client.MoveFile(CurrentPath.TrimEnd('/') + "/" + fileData.Name, newPath); + else + await Client.MoveDirectory(CurrentPath.TrimEnd('/') + "/" + fileData.Name, newPath); + } + + public override async Task Compress(params FileData[] files) + { + await EnsureConnect(); + + throw new NotImplementedException(); + } + + public override async Task Decompress(FileData fileData) + { + await EnsureConnect(); + + throw new NotImplementedException(); + } + + public override Task GetLaunchUrl() + { + return Task.FromResult( + $"ftp://{FtpUser}:{FtpPassword}@{FtpHost}:{FtpPort}/"); + } + + public override object Clone() + { + return new FtpFileAccess(FtpHost, FtpPort, FtpUser, FtpPassword); + } +} \ No newline at end of file diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 9609e64..2c6662f 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -20,6 +20,7 @@ + diff --git a/Moonlight/Shared/Views/Test.razor b/Moonlight/Shared/Views/Test.razor index eafabd5..db4a286 100644 --- a/Moonlight/Shared/Views/Test.razor +++ b/Moonlight/Shared/Views/Test.razor @@ -27,12 +27,7 @@ private Task Load(LazyLoader arg) { - var server = ServerRepository - .Get() - .Include(x => x.Node) - .First(); - - FileAccess = new WingsFileAccess(WingsApiHelper, WingsJwtHelper, server, ConfigService, User); + FileAccess = new FtpFileAccess("vps01.so.host.endelon.link", 21, "example.com", "61P8JZzfjSNyhtZl"); return Task.CompletedTask; } diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index 429e88a..3c60d0d 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -482,3 +482,5 @@ Node offline;Node offline The node the server is running on is currently offline;The node the server is running on is currently offline Server not found;Server not found A server with that id cannot be found or you have no access for this server;A server with that id cannot be found or you have no access for this server +Compress;Compress +Decompress;Decompress