<commit_before>﻿//-----------------------------------------------------------------------
// <copyright file="BlstCommandHandler.cs" company="Fubar Development Junker">
//     Copyright (c) Fubar Development Junker. All rights reserved.
// </copyright>
// <author><NAME></author>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

using Sockets.Plugin.Abstractions;

namespace FubarDev.FtpServer.CommandHandlers
{
    /// <summary>
    /// This is an extension which lists all active background transfers
    /// </summary>
    public class BlstCommandHandler : FtpCommandHandler
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BlstCommandHandler"/> class.
        /// </summary>
        /// <param name="connection">The connection for which this command handler is created for.</param>
        public BlstCommandHandler(FtpConnection connection)
            : base(connection, "BLST")
        {
            SupportedExtensions = new List<string>
            {
                "BLST",
            };
        }

        /// <inheritdoc/>
        public override IReadOnlyCollection<string> SupportedExtensions { get; }

        /// <inheritdoc/>
        public override async Task<FtpResponse> Process(FtpCommand command, CancellationToken cancellationToken)
        {
            string mode = (string.IsNullOrEmpty(command.Argument) ? "data" : command.Argument).ToLowerInvariant();

            switch (mode)
            {
                case "data":
                    return await SendWithDataConnection(cancellationToken);
                case "direct":
                    return await SendDirectly(cancellationToken);
            }

            return new FtpResponse(501, $"Mode {mode} not supported.");
        }

        private async Task<FtpResponse> SendDirectly(CancellationToken cancellationToken)
        {
            var taskStates = Server.GetBackgroundTaskStates();
            if (taskStates.Count == 0)
                return await Task.FromResult(new FtpResponse(211, "No background tasks"));

            await Connection.Write("211-Active background tasks:", cancellationToken);
            foreach (var entry in taskStates)
            {
                var line = $"{entry.Item2.ToString().PadRight(12)} {entry.Item1}";
                Connection.Log?.Debug(line);
                await Connection.Write($" {line}", cancellationToken);
            }

            return await Task.FromResult(new FtpResponse(211, "END"));
        }

        private async Task<FtpResponse> SendWithDataConnection(CancellationToken cancellationToken)
        {
            await Connection.Write(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 writer = new StreamWriter(responseSocket.WriteStream, encoding, 4096, true)
                {
                    NewLine = "\r\n",
                })
                {
                    var taskStates = Server.GetBackgroundTaskStates();
                    foreach (var entry in taskStates)
                    {
                        var line = $"{entry.Item2.ToString().PadRight(12)} {entry.Item1}";
                        Connection.Log?.Debug(line);
                        await writer.WriteLineAsync(line);
                    }
                }
            }
            finally
            {
                responseSocket.Dispose();
            }

            // Use 250 when the connection stays open.
            return new FtpResponse(250, "Closing data connection.");
        }
    }
}
<commit_msg>Removed superfluous debug output<commit_after>﻿//-----------------------------------------------------------------------
// <copyright file="BlstCommandHandler.cs" company="Fubar Development Junker">
//     Copyright (c) Fubar Development Junker. All rights reserved.
// </copyright>
// <author><NAME></author>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

using Sockets.Plugin.Abstractions;

namespace FubarDev.FtpServer.CommandHandlers
{
    /// <summary>
    /// This is an extension which lists all active background transfers
    /// </summary>
    public class BlstCommandHandler : FtpCommandHandler
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BlstCommandHandler"/> class.
        /// </summary>
        /// <param name="connection">The connection for which this command handler is created for.</param>
        public BlstCommandHandler(FtpConnection connection)
            : base(connection, "BLST")
        {
            SupportedExtensions = new List<string>
            {
                "BLST",
            };
        }

        /// <inheritdoc/>
        public override IReadOnlyCollection<string> SupportedExtensions { get; }

        /// <inheritdoc/>
        public override async Task<FtpResponse> Process(FtpCommand command, CancellationToken cancellationToken)
        {
            string mode = (string.IsNullOrEmpty(command.Argument) ? "data" : command.Argument).ToLowerInvariant();

            switch (mode)
            {
                case "data":
                    return await SendWithDataConnection(cancellationToken);
                case "direct":
                    return await SendDirectly(cancellationToken);
            }

            return new FtpResponse(501, $"Mode {mode} not supported.");
        }

        private async Task<FtpResponse> SendDirectly(CancellationToken cancellationToken)
        {
            var taskStates = Server.GetBackgroundTaskStates();
            if (taskStates.Count == 0)
                return await Task.FromResult(new FtpResponse(211, "No background tasks"));

            await Connection.Write("211-Active background tasks:", cancellationToken);
            foreach (var entry in taskStates)
            {
                var line = $"{entry.Item2.ToString().PadRight(12)} {entry.Item1}";
                await Connection.Write($" {line}", cancellationToken);
            }

            return await Task.FromResult(new FtpResponse(211, "END"));
        }

        private async Task<FtpResponse> SendWithDataConnection(CancellationToken cancellationToken)
        {
            await Connection.Write(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 writer = new StreamWriter(responseSocket.WriteStream, encoding, 4096, true)
                {
                    NewLine = "\r\n",
                })
                {
                    var taskStates = Server.GetBackgroundTaskStates();
                    foreach (var entry in taskStates)
                    {
                        var line = $"{entry.Item2.ToString().PadRight(12)} {entry.Item1}";
                        Connection.Log?.Debug(line);
                        await writer.WriteLineAsync(line);
                    }
                }
            }
            finally
            {
                responseSocket.Dispose();
            }

            // Use 250 when the connection stays open.
            return new FtpResponse(250, "Closing data connection.");
        }
    }
}

{'fraction_non_alphanumeric': 0.12885085574572128, 'fraction_numerical': 0.009046454767726161, 'mean_word_length': 1.5946717411988582, 'pattern_counts': {'":': 4, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '932992', 'n_tokens_mistral': 1946, 'n_tokens_neox': 1860, 'n_words': 462}