/// <summary> /// Receive file from FTP data connection and write it to filesystem. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> private void DoStor(FtpClient ftpClient, FtpCommand command) { var ep = new EndPoint(Address.Zero, 0); var data = ftpClient.Data.Receive(ref ep); try { File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); } catch { ftpClient.SendReply(550, "Requested action not taken."); } ftpClient.Data.Close(); ftpClient.SendReply(226, "Transfer complete."); }
/// <summary> /// Process PASV command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessPasv(FtpClient ftpClient, FtpCommand command) { /* * TODO: - Fix new TCP SYN connection (https://stackoverflow.com/questions/67824462/why-does-my-ftp-client-open-multiple-control-connection) * - Find port dynamically. */ ftpClient.SendReply(502, "Command not implemented."); /* * int port = 20; * var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); * * ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); * * ftpClient.DataListener = new TcpListener(port); * ftpClient.DataListener.Start(); * * ftpClient.Mode = TransferMode.PASV;*/ }
/// <summary> /// Process CDUP command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessCdup(FtpClient ftpClient, FtpCommand command) { try { var root = FileSystem.GetDirectory(CurrentDirectory); if (CurrentDirectory.Length > 3) { CurrentDirectory = root.mParent.mFullPath; ftpClient.SendReply(250, "Requested file action okay."); } else { ftpClient.SendReply(550, "Requested action not taken."); } } catch { ftpClient.SendReply(550, "Requested action not taken."); } }
/// <summary> /// Process PASS command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessPass(FtpClient ftpClient, FtpCommand command) { if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; } if (ftpClient.Username == "anonymous") { ftpClient.SendReply(530, "Login incorrect."); } else if (String.IsNullOrEmpty(ftpClient.Username)) { ftpClient.SendReply(332, "Need account for login."); } else { ftpClient.Password = command.Content; ftpClient.Connected = true; ftpClient.SendReply(230, "User logged in, proceed."); } }
/// <summary> /// Process USER command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessUser(FtpClient ftpClient, FtpCommand command) { if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; } if (command.Content == "anonymous") { ftpClient.Username = command.Content; ftpClient.Connected = true; ftpClient.SendReply(230, "User logged in, proceed."); } else if (String.IsNullOrEmpty(ftpClient.Username)) { ftpClient.Username = command.Content; ftpClient.SendReply(331, "User name okay, need password."); } else { ftpClient.SendReply(550, "Requested action not taken."); } }
/// <summary> /// Process MKD command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessMkd(FtpClient ftpClient, FtpCommand command) { if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; } try { if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) { ftpClient.SendReply(550, "Requested action not taken."); } else { Directory.CreateDirectory(CurrentDirectory + "\\" + command.Content); ftpClient.SendReply(200, "Command okay."); } } catch { ftpClient.SendReply(550, "Requested action not taken."); } }
/// <summary> /// Process DELE command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessDele(FtpClient ftpClient, FtpCommand command) { if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; } try { if (File.Exists(CurrentDirectory + "\\" + command.Content)) { File.Delete(CurrentDirectory + "\\" + command.Content); ftpClient.SendReply(250, "Requested file action okay, completed."); } else { ftpClient.SendReply(550, "Requested action not taken."); } } catch { ftpClient.SendReply(550, "Requested action not taken."); } }
/// <summary> /// Process QUIT command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessQuit(FtpClient ftpClient, FtpCommand command) { ftpClient.SendReply(221, "Service closing control connection."); ftpClient.Control.Close(); }
/// <summary> /// Process incoming FTP command. /// </summary> /// <param name="ftpClient">FTP Client.</param> /// <param name="command">FTP Command.</param> internal void ProcessRequest(FtpClient ftpClient, FtpCommand command) { if (command.Command == "USER") { ProcessUser(ftpClient, command); } else if (command.Command == "PASS") { ProcessPass(ftpClient, command); } else { if (ftpClient.IsConnected()) { switch (command.Command) { case "CWD": ProcessCwd(ftpClient, command); break; case "SYST": ftpClient.SendReply(215, "CosmosOS"); break; case "CDUP": ProcessCdup(ftpClient, command); break; case "QUIT": ProcessQuit(ftpClient, command); break; case "DELE": ProcessDele(ftpClient, command); break; case "PWD": ProcessPwd(ftpClient, command); break; case "PASV": ProcessPasv(ftpClient, command); break; case "PORT": ProcessPort(ftpClient, command); break; case "HELP": ftpClient.SendReply(200, "Help done."); break; case "NOOP": ftpClient.SendReply(200, "Command okay."); break; case "RETR": ProcessRetr(ftpClient, command); break; case "STOR": ProcessStor(ftpClient, command); break; case "RMD": ProcessRmd(ftpClient, command); break; case "MKD": ProcessMkd(ftpClient, command); break; case "LIST": ProcessList(ftpClient, command); break; case "TYPE": ftpClient.SendReply(200, "Command okay."); break; default: ftpClient.SendReply(500, "Unknown command."); break; } } } }