void Init() { _serverConfig = FTPServerConfigManager.Get(); skinWaterTextBox1.Text = _serverConfig.IP.ToString(); skinWaterTextBox2.Text = _serverConfig.Port.ToString(); if (_serverConfig.Users == null) { _serverConfig.Users = new ConcurrentDictionary <string, FTPUser>(); } if (!_serverConfig.Users.Any()) { _serverConfig.Users.TryAdd("anonymous", new FTPUser("anonymous", "*****@*****.**", "c:\\")); FTPServerConfigManager.Save(); } _ftpServerUsers = SerializeHelper.Deserialize <List <FtpServerUser> >(SerializeHelper.Serialize(_serverConfig.Users.Values)); dataGridView1.DataSource = null; dataGridView1.DataSource = _ftpServerUsers; dataGridView1.AllowUserToAddRows = true; }
/// <summary> /// 修改用户 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex >= 0 && e.RowIndex >= 0) { var row = dataGridView1.Rows[e.RowIndex]; var userName = row.Cells[0].Value.ToString(); var oUser = _ftpServerUsers.FirstOrDefault(b => b.UserName == userName); if (oUser == null) { return; } var cf = new CreateUserForm(oUser); if (cf.ShowDialog(this) == DialogResult.OK) { var user = cf.FtpServerUser; _ftpServerUsers.Remove(oUser); _ftpServerUsers.Add(user); FTPServerConfigManager.SetUser(user.UserName, user.Password, user.Root); FTPServerConfigManager.Save(); Init(); } } }
/// <summary> /// 删除用户 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void skinButton2_Click(object sender, EventArgs e) { if (MessageBox.Show("确认要删除用户吗?", "SAEA.FTP Test", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { List <string> userNames = new List <string>(); var rows = dataGridView1.SelectedRows; if (rows == null || rows.Count == 0) { var cells = dataGridView1.SelectedCells; if (cells == null && cells.Count == 0) { MessageBox.Show("请选择要删除的用户"); return; } else { foreach (DataGridViewTextBoxCell item in cells) { userNames.Add(dataGridView1.Rows[item.RowIndex].Cells[0].Value.ToString()); } } } foreach (DataGridViewRow item in rows) { userNames.Add(item.Cells[0].Value.ToString()); } if (!userNames.Any()) { MessageBox.Show("请选择要删除的用户"); return; } else { foreach (var userName in userNames) { if (!string.IsNullOrEmpty(userName)) { var user = _ftpServerUsers.FirstOrDefault(b => b.UserName == userName); if (user != null) { _ftpServerUsers.Remove(user); FTPServerConfigManager.DelUser(userName); } } } FTPServerConfigManager.Save(); Init(); } } }
public FTPServer(string ip, ushort port = 21, int bufferSize = 10240) { _serverConfig = FTPServerConfigManager.Get(); _serverConfig.Port = port; _serverConfig.BufferSize = bufferSize; FTPServerConfigManager.Save(); _cmdSocket = new ServerSocket(_serverConfig); _cmdSocket.OnReceived += _serverSocket_OnReceived; }
private void skinButton1_Click(object sender, EventArgs e) { if (skinButton1.Text == "Start") { var ip = skinWaterTextBox1.Text; var portStr = skinWaterTextBox2.Text; if (!IPHelper.IsIP(ip)) { MessageBox.Show("输入的ip有误"); Log("输入的ip有误"); return; } if (!IPHelper.IsPort(portStr, out ushort port)) { MessageBox.Show("输入的ip有误"); Log("输入的ip有误"); return; } _serverConfig.IP = ip; _serverConfig.Port = port; FTPServerConfigManager.Save(); Log("FTPServer正在启动中..."); skinButton1.Text = "Stop"; if (_ftpServer == null) { _ftpServer = new FTPServer(_serverConfig.IP, _serverConfig.Port, _serverConfig.BufferSize); _ftpServer.OnLog += _ftpServer_OnLog; } _ftpServer.Start(); Log("FTPServer已启动"); } else { skinButton1.Text = "Start"; _ftpServer.Stop(); _ftpServer = null; } }
/// <summary> /// 添加用户 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void skinButton3_Click(object sender, EventArgs e) { var cf = new CreateUserForm(); if (cf.ShowDialog(this) == DialogResult.OK) { var user = cf.FtpServerUser; if (FTPServerConfigManager.GetUser(user.UserName) != null) { MessageBox.Show("当前用户已存在!"); return; } _ftpServerUsers.Add(user); FTPServerConfigManager.SetUser(user.UserName, user.Password, user.Root); FTPServerConfigManager.Save(); Init(); } }
/// <summary> /// 断开连接 /// </summary> /// <param name="id"></param> private void _cmdSocket_OnDisconnected(string id) { var userName = FTPServerConfigManager.GetUserBind(id); if (string.IsNullOrEmpty(userName)) { return; } var user = FTPServerConfigManager.GetUser(userName); if (user == null) { return; } user.CurrentFtpPath = user.Root; user.CurrentPath = "/"; user.IsLogin = false; FTPServerConfigManager.RemoveUserBind(id); FTPServerConfigManager.Save(); }
private void _serverSocket_OnReceived(string id, string msg) { try { OnLog($"收到命令:{msg.Trim()}", null); var cr = ClientRequest.Parse(msg); var cmd = Enum.Parse(typeof(FTPCommand), cr.Cmd); var userName = FTPServerConfigManager.GetUserBind(id); var user = FTPServerConfigManager.GetUser(userName); switch (cmd) { case FTPCommand.USER: if (!string.IsNullOrEmpty(cr.Arg)) { userName = cr.Arg; user = FTPServerConfigManager.GetUser(userName); if (user == null) { _cmdSocket.Reply(id, ServerResponseCode.无效的用户名, "Invalid user name."); } else { if (FTPServerConfigManager.GetUserBind(id) == user.UserName) { if (user.IsLogin == true) { _cmdSocket.Reply(id, ServerResponseCode.初始命令没有执行, "Already logged-in."); } else { _cmdSocket.Reply(id, ServerResponseCode.要求密码, "User name okay, need password."); } } else { if (user.UserName.ToLower() == "anonymous") { FTPServerConfigManager.UserBinding(id, user.UserName); _cmdSocket.Reply(id, ServerResponseCode.登录成功, "User logged in, proceed."); } else { FTPServerConfigManager.UserBinding(id, user.UserName); _cmdSocket.Reply(id, ServerResponseCode.要求密码, "User name okay, need password."); } } } } return; case FTPCommand.PASS: if (!string.IsNullOrEmpty(userName)) { if (user.IsLogin) { _cmdSocket.Reply(id, ServerResponseCode.初始命令没有执行, "Already logged-in."); } else { if (FTPServerConfigManager.UserLogin(userName, cr.Arg)) { _cmdSocket.Reply(id, ServerResponseCode.登录成功, "User logged in, proceed."); OnLog($"{userName}登录成功", null); } else { _cmdSocket.Reply(id, ServerResponseCode.无效的用户名, "Authentication failed."); } } } else { _cmdSocket.Reply(id, ServerResponseCode.错误指令序列, "Login with USER first."); } return; case FTPCommand.SYST: _cmdSocket.Reply(id, ServerResponseCode.系统类型回复, "WINDOWS Type: SAEA FTP Server"); return; case FTPCommand.OPTS: case FTPCommand.NOOP: _cmdSocket.Reply(id, ServerResponseCode.成功, "WINDOWS Type: SAEA FTP Server"); _cmdSocket.Reply(id, ServerResponseCode.成功, "Command okay."); return; case FTPCommand.QUIT: _cmdSocket.Reply(id, ServerResponseCode.退出网络, "SAEA FTP: Goodbye."); OnLog($"{userName}退出网络", null); return; } if (user == null || !user.IsLogin) { _cmdSocket.Reply(id, ServerResponseCode.错误指令序列, "Login with USER first."); return; } if (string.IsNullOrWhiteSpace(user.CurrentFtpPath) || user.CurrentFtpPath == "/" || user.CurrentFtpPath == "\\") { user.CurrentPath = user.Root; user.CurrentFtpPath = "/"; } switch (cmd) { case FTPCommand.CWD: if (PathHelper.Combine(user.CurrentPath, cr.Arg, out string newDirPath)) { user.CurrentFtpPath += cr.Arg + "/"; user.CurrentFtpPath = user.CurrentFtpPath.Replace("//", "/"); user.CurrentPath = newDirPath; _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "Command okay."); } else { _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "No such directory."); } break; case FTPCommand.CDUP: var parentDir = PathHelper.GetParent(user.CurrentPath); if (parentDir != null) { if (!PathHelper.IsParent(parentDir.ToString(), user.Root)) { var cstr = user.CurrentFtpPath.Substring(0, user.CurrentFtpPath.LastIndexOf("/")); user.CurrentFtpPath = cstr.Substring(0, cstr.LastIndexOf("/") + 1); user.CurrentFtpPath = user.CurrentFtpPath.Replace("//", "/"); user.CurrentPath = parentDir.ToString(); } _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "Command okay."); return; } _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "No such directory."); break; case FTPCommand.PWD: _cmdSocket.Reply(id, ServerResponseCode.路径名建立, $"\"{ user.CurrentFtpPath}\""); break; case FTPCommand.PASV: var dataPort = IPHelper.GetFreePort(); var portStr = dataPort.PortToString(); var pasvStr = $"SAEA FTPServer PASV({_serverConfig.IP.Replace(".", ",")},{portStr})"; _cmdSocket.CreateDataSocket(userName, dataPort, _serverConfig.BufferSize); OnLog($"{userName}进入被动模式,已创建数据传输Socket:{_serverConfig.IP}:{dataPort}", null); _cmdSocket.Reply(id, ServerResponseCode.进入被动模式, pasvStr); break; case FTPCommand.PORT: _cmdSocket.Reply(id, ServerResponseCode.禁用, "Port is disabled."); break; case FTPCommand.MLSD: if (!string.IsNullOrEmpty(cr.Arg) && cr.Arg != "/") { PathHelper.Combine(user.CurrentPath, cr.Arg, out newDirPath); if (string.IsNullOrEmpty(newDirPath)) { _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "No such directory."); return; } } var dirList = PathHelper.GetDirectories(user.CurrentPath, out List <FileInfo> fileList); StringBuilder sb = new StringBuilder(); if (dirList != null && dirList.Any()) { foreach (var item in dirList) { if (item == dirList.Last()) { sb.Append($"type=dir;modify={item.LastWriteTime.ToFileTimeUtc()}; {item.Name}"); } else { sb.AppendLine($"type=dir;modify={item.LastWriteTime.ToFileTimeUtc()}; {item.Name}"); } } } if (fileList != null && fileList.Any()) { if (sb.Length > 0) { sb.Append(Environment.NewLine); } foreach (var item in fileList) { if (item == fileList.Last()) { sb.Append($"type=file;modify={item.LastWriteTime.ToFileTimeUtc()};size={item.Length}; {item.Name}"); } else { sb.AppendLine($"type=file;modify={item.LastWriteTime.ToFileTimeUtc()};size={item.Length}; {item.Name}"); } } } var str = sb.ToString(); _cmdSocket.SendData(userName, Encoding.UTF8.GetBytes(str)); OnLog($"已发送数据到{userName}", null); _cmdSocket.Reply(id, ServerResponseCode.打开连接, "File status okay; about to open data connection."); break; case FTPCommand.NLST: if (!string.IsNullOrEmpty(cr.Arg) && cr.Arg != "/") { PathHelper.Combine(user.CurrentPath, cr.Arg, out newDirPath); if (string.IsNullOrEmpty(newDirPath)) { _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "No such directory."); return; } } dirList = PathHelper.GetDirectories(user.CurrentPath, out fileList); sb = new StringBuilder(); if (dirList != null && dirList.Any()) { foreach (var item in dirList) { if (item == dirList.Last()) { sb.Append($"{item.FullName.Replace(user.CurrentPath, "").Replace("\\", "/")}"); } else { sb.AppendLine($"{item.FullName.Replace(user.CurrentPath, "").Replace("\\", "/")}"); } } } if (fileList != null && fileList.Any()) { if (sb.Length > 0) { sb.Append(Environment.NewLine); } foreach (var item in fileList) { if (item == fileList.Last()) { sb.Append($"{item.FullName.Replace(user.CurrentPath, "").Replace("\\", "/")}"); } else { sb.AppendLine($"{item.FullName.Replace(user.CurrentPath, "").Replace("\\", "/")}"); } } } str = sb.ToString(); if (!string.IsNullOrEmpty(str)) { _cmdSocket.SendData(userName, Encoding.UTF8.GetBytes(str)); OnLog($"已发送数据到{userName}", null); } _cmdSocket.Reply(id, ServerResponseCode.打开连接, "File status okay; about to open data connection."); break; case FTPCommand.SIZE: var fileName = cr.Arg; var filePath = PathHelper.Combine(user.CurrentPath, fileName); var fileInfo = FileHelper.GetFileInfo(filePath); if (fileInfo != null) { _cmdSocket.Reply(id, ServerResponseCode.文件状态回复, fileInfo.Length.ToString()); } else { _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "No such file."); } break; case FTPCommand.RETR: fileName = cr.Arg; filePath = PathHelper.Combine(user.CurrentPath, fileName); fileInfo = FileHelper.GetFileInfo(filePath); if (fileInfo != null) { _cmdSocket.Reply(id, ServerResponseCode.打开连接, fileInfo.Length.ToString()); _cmdSocket.SendFile(userName, filePath); OnLog($"已发送文件{fileName}到{userName}", null); } else { _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "No such file."); } break; case FTPCommand.STOR: try { fileName = cr.Arg; filePath = PathHelper.Combine(user.CurrentPath, fileName); if (!string.IsNullOrEmpty(filePath)) { _cmdSocket.Reply(id, ServerResponseCode.打开连接, "Opening data connection."); _cmdSocket.ReceiveFile(userName, filePath); OnLog($"已从{userName}接收到文件{fileName}", null); } else { _cmdSocket.Reply(id, ServerResponseCode.输出文件出错, "Error on output file."); } break; } catch (Exception ex) { OnLog($"从{userName}接收文件时出现异常", ex); } break; case FTPCommand.MKD: try { fileName = cr.Arg; filePath = PathHelper.Combine(user.CurrentPath, fileName); PathHelper.CreateDir(filePath); _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "Directory created."); break; } catch (Exception ex) { OnLog($"{userName}创建目录{cr.Arg}时出现异常", ex); } _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "Cannot create directory."); break; case FTPCommand.RMD: try { fileName = cr.Arg; filePath = PathHelper.Combine(user.CurrentPath, fileName); PathHelper.Remove(filePath); _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "Directory removed."); break; } catch (Exception ex) { OnLog($"{userName}移除目录{cr.Arg}时出现异常", ex); } _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "Cannot remove directory."); break; case FTPCommand.DELE: try { fileName = cr.Arg; filePath = PathHelper.Combine(user.CurrentPath, fileName); FileHelper.Remove(filePath); _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "File removed."); break; } catch (Exception ex) { OnLog($"{userName}移除文件{cr.Arg}时出现异常", ex); } _cmdSocket.Reply(id, ServerResponseCode.找不到文件或文件夹, "Cannot remove File."); break; } } catch (Exception ex) { OnLog("FTPServer Error OnReceive 未知的命令", ex); } }
private void _serverSocket_OnReceived(string id, string msg) { var cr = ClientRequest.Parse(msg); var cmd = Enum.Parse(typeof(FTPCommand), cr.Cmd); var userName = FTPServerConfigManager.GetUserBind(id); var user = FTPServerConfigManager.GetUser(userName); switch (cmd) { case FTPCommand.USER: if (!string.IsNullOrEmpty(cr.Arg)) { if (user == null) { _cmdSocket.Reply(id, ServerResponseCode.无效的用户名, "Invalid user name."); } else { if (FTPServerConfigManager.GetUserBind(id) == user.UserName) { if (user.IsLogin == true) { _cmdSocket.Reply(id, ServerResponseCode.初始命令没有执行, "Already logged-in."); } else { _cmdSocket.Reply(id, ServerResponseCode.要求密码, "User name okay, need password."); } } else { if (user.UserName.ToLower() == "anonymous") { FTPServerConfigManager.UserBinding(id, user.UserName); _cmdSocket.Reply(id, ServerResponseCode.登录因特网, "User logged in, proceed."); } else { FTPServerConfigManager.UserBinding(id, user.UserName); _cmdSocket.Reply(id, ServerResponseCode.要求密码, "User name okay, need password."); } } } } return; case FTPCommand.PASS: if (!string.IsNullOrEmpty(userName)) { if (user.IsLogin) { _cmdSocket.Reply(id, ServerResponseCode.初始命令没有执行, "Already logged-in."); } else { if (FTPServerConfigManager.UserLogin(userName, cr.Arg)) { _cmdSocket.Reply(id, ServerResponseCode.登录因特网, "User logged in, proceed."); } else { _cmdSocket.Reply(id, ServerResponseCode.无效的用户名, "Authentication failed."); } } } else { _cmdSocket.Reply(id, ServerResponseCode.错误指令序列, "Login with USER first."); } return; case FTPCommand.SYST: _cmdSocket.Reply(id, ServerResponseCode.系统类型回复, "WINDOWS Type: SAEA FTP Server"); return; case FTPCommand.NOOP: _cmdSocket.Reply(id, ServerResponseCode.成功, "Command okay."); return; } if (user == null || !user.IsLogin) { _cmdSocket.Reply(id, ServerResponseCode.错误指令序列, "Login with USER first."); return; } switch (cmd) { case FTPCommand.CWD: if (PathHelper.Exists(user.Root, cr.Arg, out string newDirPath)) { user.CurrentFtpPath = newDirPath; _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "Command okay."); } else { _cmdSocket.Reply(id, ServerResponseCode.页文件不可用, "No such directory."); } break; case FTPCommand.CDUP: if (PathHelper.Exists(user.CurrentFtpPath, "../", out newDirPath)) { if (!PathHelper.IsParent(newDirPath, user.Root)) { user.CurrentFtpPath = newDirPath; _cmdSocket.Reply(id, ServerResponseCode.文件行为完成, "Command okay."); return; } } _cmdSocket.Reply(id, ServerResponseCode.页文件不可用, "No such directory."); break; case FTPCommand.PWD: _cmdSocket.Reply(id, ServerResponseCode.路径名建立, $"\"{ user.CurrentFtpPath}\""); break; case FTPCommand.PASV: var dataPort = IPHelper.GetFreePort(); var portStr = dataPort.PortToString(); var pasvStr = $"SAEA FTPServer PASV({_serverConfig.IP},{portStr})"; _cmdSocket.CreateDataSocket(userName, dataPort, _serverConfig.BufferSize); _cmdSocket.Reply(id, ServerResponseCode.进入被动模式, pasvStr); break; case FTPCommand.MLSD: var path = user.CurrentFtpPath; if (!string.IsNullOrEmpty(cr.Arg) && cr.Arg != "/") { if (PathHelper.Exists(path, cr.Arg, out newDirPath)) { path = newDirPath; } } var dirList = PathHelper.GetDirectories(path, out List <FileInfo> fileList); StringBuilder sb = new StringBuilder(); if (dirList != null && dirList.Any()) { foreach (var item in dirList) { sb.AppendLine($"type=dir;modify={item.LastWriteTime.ToFileTimeUtc()}; {item.Name}"); } } if (fileList != null && fileList.Any()) { foreach (var item in fileList) { sb.AppendLine($"type=file;modify={item.LastWriteTime.ToFileTimeUtc()}; {item.Name}"); } } var str = sb.ToString(); if (!string.IsNullOrEmpty(str)) { _cmdSocket.SendData(userName, Encoding.UTF8.GetBytes(str)); } break; case FTPCommand.NLST: path = user.CurrentFtpPath; if (!string.IsNullOrEmpty(cr.Arg) && cr.Arg != "/") { if (PathHelper.Exists(path, cr.Arg, out newDirPath)) { path = newDirPath; } } dirList = PathHelper.GetDirectories(path, out fileList); sb = new StringBuilder(); if (dirList != null && dirList.Any()) { foreach (var item in dirList) { sb.AppendLine($"{item.FullName.Replace(user.CurrentFtpPath, "").Replace("\\", "/")}"); } } if (fileList != null && fileList.Any()) { foreach (var item in fileList) { sb.AppendLine($"{item.FullName.Replace(user.CurrentFtpPath, "").Replace("\\", "/")}"); } } str = sb.ToString(); if (!string.IsNullOrEmpty(str)) { _cmdSocket.SendData(userName, Encoding.UTF8.GetBytes(str)); } break; } }