Exemple #1
0
        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."));
        }
Exemple #2
0
        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."));
        }