92 lines
2.7 KiB
C#
92 lines
2.7 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace DearFTP.Connection.Commands
|
|
{
|
|
class RetrieveCommand : ICommand
|
|
{
|
|
public const int BufferSize = 4096;
|
|
|
|
public string[] Aliases { get; } = new string[]
|
|
{
|
|
"RETR"
|
|
};
|
|
|
|
public void Execute(Session session, FtpStream stream, string alias, string argument)
|
|
{
|
|
var dataConnection = session.DataConnection;
|
|
|
|
if (!dataConnection.IsTlsProtected && !dataConnection.IsAvailable)
|
|
{
|
|
stream.Send(ResponseCode.DataConnectionOpenError, "Passive mode not activated.");
|
|
return;
|
|
}
|
|
|
|
var (_, realPath, isDirectory) = session.NavigablePath.GetSystemFilePath(argument);
|
|
|
|
if (realPath == null)
|
|
{
|
|
stream.Send(ResponseCode.FileUnavailable, "Requested file does not exist.");
|
|
return;
|
|
}
|
|
|
|
if (isDirectory)
|
|
{
|
|
stream.Send(ResponseCode.FileUnavailable, "Requested file is a directory.");
|
|
return;
|
|
}
|
|
|
|
stream.Send(ResponseCode.FileStatusOK, "File coming.");
|
|
|
|
if (dataConnection.IsTlsProtected && !dataConnection.IsAvailable)
|
|
{
|
|
stream.Send(ResponseCode.DataConnectionOpenError, "Passive mode not activated.");
|
|
return;
|
|
}
|
|
|
|
int restartPosition = session.RestartPosition;
|
|
session.RestartPosition = 0;
|
|
|
|
SendFile(dataConnection.Stream, realPath, restartPosition);
|
|
|
|
dataConnection.Close();
|
|
|
|
stream.Send(ResponseCode.CloseDataConnection, "File sent.");
|
|
}
|
|
|
|
private void SendFile(Stream stream, string path, int offset)
|
|
{
|
|
using (var file = File.OpenRead(path))
|
|
{
|
|
if (offset != 0)
|
|
{
|
|
file.Seek(offset, SeekOrigin.Begin);
|
|
}
|
|
|
|
Span<byte> buffer = stackalloc byte[BufferSize];
|
|
long bytesToWrite = Math.Min(file.Length - file.Position, BufferSize);
|
|
|
|
while (file.Read(buffer) > 0)
|
|
{
|
|
try
|
|
{
|
|
if (bytesToWrite < BufferSize)
|
|
{
|
|
stream.Write(buffer.Slice(0, (int)bytesToWrite));
|
|
break;
|
|
}
|
|
|
|
stream.Write(buffer);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bytesToWrite = Math.Min(file.Length - file.Position, BufferSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|