private async Task <FtpResponse> ExecuteSendAsync( TcpClient responseSocket, Stack <IUnixDirectoryEntry> path, IUnixDirectoryEntry dirEntry, CancellationToken cancellationToken) { var encoding = Data.NlstEncoding ?? Connection.Encoding; using (var stream = await Connection.CreateEncryptedStream(responseSocket.GetStream()).ConfigureAwait(false)) { using (var writer = new StreamWriter(stream, encoding, 4096, true) { NewLine = "\r\n", }) { var entries = await Data.FileSystem.GetEntriesAsync(dirEntry, cancellationToken).ConfigureAwait(false); var enumerator = new DirectoryListingEnumerator(entries, Data.FileSystem, path, true); var formatter = new FactsListFormatter(Data.User, enumerator, Data.ActiveMlstFacts, false); while (enumerator.MoveNext()) { var name = enumerator.Name; var entry = enumerator.Entry; var line = formatter.Format(entry, name); Connection.Log?.LogDebug(line); await writer.WriteLineAsync(line).ConfigureAwait(false); } await writer.FlushAsync().ConfigureAwait(false); } await stream.FlushAsync(cancellationToken).ConfigureAwait(false); } // Use 250 when the connection stays open. return(new FtpResponse(226, "Closing data connection.")); }
private async Task <FtpResponse> ProcessMlstAsync(FtpCommand command, CancellationToken cancellationToken) { var argument = command.Argument; var path = Data.Path.Clone(); IUnixFileSystemEntry targetEntry; if (string.IsNullOrEmpty(argument)) { targetEntry = path.Count == 0 ? Data.FileSystem.Root : path.Peek(); } else { var foundEntry = await Data.FileSystem.SearchEntryAsync(path, argument, cancellationToken).ConfigureAwait(false); if (foundEntry?.Entry == null) { return(new FtpResponse(550, "File system entry not found.")); } targetEntry = foundEntry.Entry; } await Connection.WriteAsync($"250- {targetEntry.Name}", cancellationToken).ConfigureAwait(false); var entries = new List <IUnixFileSystemEntry>() { targetEntry, }; var enumerator = new DirectoryListingEnumerator(entries, Data.FileSystem, path, false); var formatter = new FactsListFormatter(Data.User, enumerator, Data.ActiveMlstFacts, true); while (enumerator.MoveNext()) { var name = enumerator.Name; var entry = enumerator.Entry; var line = formatter.Format(entry, name); await Connection.WriteAsync($" {line}", cancellationToken).ConfigureAwait(false); } return(new FtpResponse(250, "End")); }
private async Task <IFtpResponse?> ExecuteSendAsync( IFtpDataConnection dataConnection, ClaimsPrincipal user, IUnixFileSystem fileSystem, Stack <IUnixDirectoryEntry> path, IUnixDirectoryEntry dirEntry, IMlstFactsFeature factsFeature, CancellationToken cancellationToken) { var encoding = Connection.Features.Get <IEncodingFeature>().Encoding; var stream = dataConnection.Stream; using (var writer = new StreamWriter(stream, encoding, 4096, true) { NewLine = "\r\n", }) { var entries = await fileSystem.GetEntriesAsync(dirEntry, cancellationToken).ConfigureAwait(false); var enumerator = new DirectoryListingEnumerator(entries, fileSystem, path, true); var formatter = new FactsListFormatter(user, enumerator, factsFeature.ActiveMlstFacts, false); while (enumerator.MoveNext()) { var name = enumerator.Name; var entry = enumerator.Entry; var line = formatter.Format(entry, name); _logger?.LogTrace(line); await writer.WriteLineAsync(line).ConfigureAwait(false); } await writer.FlushAsync().ConfigureAwait(false); } // Use 250 when the connection stays open. return(new FtpResponse(226, T("Closing data connection."))); }
private async Task <FtpResponse> ProcessMlsdAsync(FtpCommand command, CancellationToken cancellationToken) { var argument = command.Argument; var path = Data.Path.Clone(); IUnixDirectoryEntry dirEntry; if (string.IsNullOrEmpty(argument)) { dirEntry = path.Count == 0 ? Data.FileSystem.Root : path.Peek(); } else { var foundEntry = await Data.FileSystem.SearchEntryAsync(path, argument, cancellationToken); if (foundEntry?.Entry == null) { return(new FtpResponse(550, "File system entry not found.")); } dirEntry = foundEntry.Entry as IUnixDirectoryEntry; if (dirEntry == null) { return(new FtpResponse(501, "Not a directory.")); } if (!dirEntry.IsRoot) { path.Push(dirEntry); } } await Connection.WriteAsync(new FtpResponse(150, "Opening data connection."), cancellationToken); ITcpSocketClient responseSocket; try { responseSocket = await Connection.CreateResponseSocket(); } catch (Exception) { return(new FtpResponse(425, "Can't open data connection.")); } try { var encoding = Data.NlstEncoding ?? Connection.Encoding; using (var stream = await Connection.CreateEncryptedStream(responseSocket.WriteStream)) { using (var writer = new StreamWriter(stream, encoding, 4096, true) { NewLine = "\r\n", }) { var entries = await Data.FileSystem.GetEntriesAsync(dirEntry, cancellationToken); var enumerator = new DirectoryListingEnumerator(entries, Data.FileSystem, path, true); var formatter = new FactsListFormatter(Data.User, enumerator, Data.ActiveMlstFacts, false); while (enumerator.MoveNext()) { var name = enumerator.Name; var entry = enumerator.Entry; var line = formatter.Format(entry, name); Connection.Log?.Debug(line); await writer.WriteLineAsync(line); } await writer.FlushAsync(); } await stream.FlushAsync(cancellationToken); } } finally { responseSocket.Dispose(); } // Use 250 when the connection stays open. return(new FtpResponse(226, "Closing data connection.")); }