Files
DearFTP/DearFTP/Connection/Commands/StoreCommand.cs
2019-07-18 13:18:15 +02:00

84 lines
2.5 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
namespace DearFTP.Connection.Commands
{
class StoreCommand : ICommand
{
public const int BufferSize = 4096;
public string[] Aliases { get; } = new string[]
{
"APPE",
"STOR",
"STOU"
};
public void Execute(Session session, FtpStream stream, string alias, string argument)
{
var dataConnection = session.DataConnection;
if (!dataConnection.IsAvailable)
{
stream.Send(ResponseCode.DataConnectionOpenError, "Passive mode not activated.");
return;
}
string path = alias.ToUpper() == "STOU" ? Path.GetRandomFileName() : argument;
var (navigablePath, realPath) = session.NavigablePath.GetNewSystemFilePath(path);
if (realPath == null)
{
stream.Send(ResponseCode.FileUnavailable, "Invalid destination path.");
return;
}
if (Directory.Exists(realPath))
{
stream.Send(ResponseCode.FileUnavailable, "A directory with this name already exists.");
return;
}
if (!session.WritablesShares.Contains(navigablePath.CurrentShare))
{
stream.Send(ResponseCode.FileUnavailable, "You don't have write access to this file.");
return;
}
stream.Send(ResponseCode.FileStatusOK, "Waiting file.");
ReceiveFile(dataConnection.Stream, realPath, alias.ToUpper() == "APPE");
dataConnection.Close();
stream.Send(ResponseCode.CloseDataConnection, "File received.");
}
private void ReceiveFile(NetworkStream stream, string path, bool append)
{
using (var file = File.Open(path, append ? FileMode.Append : FileMode.Create))
{
Span<byte> buffer = stackalloc byte[BufferSize];
int readBytes;
while ((readBytes = stream.Read(buffer)) > 0)
{
if (readBytes < BufferSize)
{
file.Write(buffer.Slice(0, readBytes));
}
else
{
file.Write(buffer);
}
}
}
}
}
}