Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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;
            }
        }