/// <summary> /// 列文件名操作 /// </summary> /// <param name="dataStream"></param> /// <param name="pathname"></param> /// <returns></returns> private Response NameListOperation(Stream dataStream, string pathname) { FtpLogEntry logEntry = new FtpLogEntry { Date = DateTime.Now, CIP = ClientIP, CSMethod = "NLST", CSUsername = _username, SCStatus = "226" }; StreamWriter dataWriter = new StreamWriter(dataStream, _currentEncoding); var nameList = _virtualFileSystem.ListFileNames(pathname); foreach (var name in nameList) { dataWriter.WriteLine(name); dataWriter.Flush(); } _log.Info(logEntry); OnLog(logEntry); return(GetResponse(FtpResponses.TRANSFER_SUCCESSFUL)); }
/// <summary> /// 文件追加操作 /// </summary> /// <param name="dataStream"></param> /// <param name="pathname"></param> /// <returns></returns> private Response AppendOperation(Stream dataStream, string pathname) { long bytes = 0; FtpLogEntry logEntry = new FtpLogEntry { Date = DateTime.Now, CIP = ClientIP, CSMethod = "APPE", CSUsername = _username, SCStatus = "226", //CSBytes = bytes.ToString(CultureInfo.InvariantCulture) }; using (FileStream fs = new FileStream(pathname, FileMode.Append, FileAccess.Write, FileShare.Read, BUFFER_SIZE, FileOptions.SequentialScan)) { bytes = CopyStream(dataStream, fs, _performanceCounter.IncrementBytesReceived); } logEntry.CSBytes = bytes.ToString(CultureInfo.InvariantCulture); _log.Info(logEntry); OnLog(logEntry); _performanceCounter.IncrementFilesReceived(); _virtualFileSystem.RefreshCurrentDirectory(); return(GetResponse(FtpResponses.TRANSFER_SUCCESSFUL)); }
/// <summary> /// 列目录操作 /// </summary> /// <param name="dataStream"></param> /// <param name="pathname"></param> /// <returns></returns> private Response ListOperation(Stream dataStream, string pathname) { DateTime now = DateTime.Now; FtpLogEntry logEntry = new FtpLogEntry { Date = now, CIP = ClientIP, CSMethod = "LIST", CSUsername = _username, SCStatus = "226" }; StreamWriter dataWriter = new StreamWriter(dataStream, _currentEncoding); var dirList = _virtualFileSystem.ListFiles(pathname); dataWriter.WriteLine(dirList.Count); //MARK:第一行表示数目 foreach (var dir in dirList) { dataWriter.WriteLine(dir); dataWriter.Flush(); } _log.Info(logEntry); OnLog(logEntry); return(GetResponse(FtpResponses.TRANSFER_SUCCESSFUL)); }
/// <summary> /// 下载操作 /// </summary> /// <param name="dataStream"></param> /// <param name="pathname"></param> /// <returns></returns> private Response RetrieveOperation(Stream dataStream, string pathname) { long bytes = 0; FtpLogEntry logEntry = new FtpLogEntry { Date = DateTime.Now, CIP = ClientIP, CSMethod = "RETR", CSUsername = _username, SCStatus = "226", }; using (FileStream fs = new FileStream(pathname, FileMode.Open, FileAccess.Read)) { fs.Seek(_transPosition, SeekOrigin.Begin); //由于是异步调用的 因此不会阻塞 bytes = CopyStream(fs, dataStream, _performanceCounter.IncrementBytesSent); } logEntry.SCBytes = bytes.ToString(CultureInfo.InvariantCulture); _log.Info(logEntry); OnLog(logEntry); _performanceCounter.IncrementFilesSent(); _virtualFileSystem.RefreshCurrentDirectory(); return(GetResponse(FtpResponses.TRANSFER_SUCCESSFUL)); }
protected override void Dispose(bool disposing) { try { if (!_disposed) { _disposed = true; if (_currentUser != null) { if (_currentUser.IsAnonymous) { _performanceCounter.DecrementAnonymousUsers(); } else { _performanceCounter.DecrementNonAnonymousUsers(); } } if (_connected) { _performanceCounter.DecrementCurrentConnections(); } if (disposing) { if (_dataClient != null) { _dataClient.Close(); _dataClient = null; } if (_sslStream != null) { _sslStream.Dispose(); _sslStream = null; } } } } finally { FtpLogEntry logEntry = new FtpLogEntry() { Date = DateTime.Now, Info = LogInfo.ConnectionTerminated.ToString() }; OnLog(logEntry); var serverConnInfos = ((FtpServer)CurrentServer).ConnectionInfos; if (serverConnInfos.Contains(ConnectionInfo)) { serverConnInfos.Remove(ConnectionInfo); } serverConnInfos.RemoveAll(t => t.ID == this.ID); base.Dispose(disposing); } }
protected override void OnStop() { if (_timer != null) { _timer.Stop(); } FtpLogEntry logEntry = new FtpLogEntry() { Date = DateTime.Now, Info = LogInfo.ServerStop.ToString() }; OnLog(logEntry); Active = false; }
protected override void OnConnected() { _performanceCounter = ((FtpServer)CurrentServer).ServerPerformanceCounter; _performanceCounter.IncrementCurrentConnections(); ConnectionInfo.ID = ID;//FIXED:注意与下一句的先后顺序 RegisterToServer(); OnLog = ((FtpServer)CurrentServer).SendLog; FtpLogEntry logEntry = new FtpLogEntry() { Date = DateTime.Now, Info = LogInfo.ConnectionEstablished.ToString() }; OnLog(logEntry); ConnectionInfo.IP = ClientIP; _connected = true; if (((FtpServer)CurrentServer).Config.Welcome != null) { Write(new Response { Code = "220-", Text = "Connected" }); foreach (var welcome in ((FtpServer)CurrentServer).Config.Welcome) { Write(new Response { Code = "", Text = welcome }); } } Write(GetResponse(FtpResponses.SERVICE_READY)); //FIXED:SSL指令可以在登陆前执行 _validCommands.AddRange(new string[] { "AUTH", "USER", "PASS", "ACCT", "QUIT", "HELP", "NOOP", "PBSZ", "PROT" }); _dataClient = new TcpClient(); Read(); }
protected override void OnStart() { _startTime = DateTime.Now; _timer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); _timer.Start(); foreach (var tcpListener in base.Listeners) { FtpLogEntry logEntry = new FtpLogEntry() { Date = DateTime.Now, Info = LogInfo.ServerStart.ToString(), SPort = tcpListener.LocalEndpoint.ToString() }; OnLog(logEntry); } Active = true; }
/// <summary> /// 上传操作 /// </summary> /// <param name="dataStream"></param> /// <param name="pathname"></param> /// <returns></returns> private Response StoreOperation(Stream dataStream, string pathname) { long bytes = 0; FtpLogEntry logEntry = new FtpLogEntry { Date = DateTime.Now, CIP = ClientIP, CSMethod = "STOR", CSUsername = _username, SCStatus = "226", }; if (VPath.ContainsInvalidPathChars(pathname)) { pathname = VPath.RemoveInvalidPathChars(pathname); } using (FileStream fs = new FileStream(pathname, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, BUFFER_SIZE, FileOptions.SequentialScan)) { //if (_lastCommand.Code == "REST") //{ // fs.Seek(_transPosition, SeekOrigin.Begin); //} fs.Seek(_transPosition, SeekOrigin.Begin); bytes = CopyStream(dataStream, fs, _performanceCounter.IncrementBytesReceived); } logEntry.CSBytes = bytes.ToString(CultureInfo.InvariantCulture); _log.Info(logEntry); OnLog(logEntry); _performanceCounter.IncrementFilesReceived(); _virtualFileSystem.RefreshCurrentDirectory(); return(GetResponse(FtpResponses.TRANSFER_SUCCESSFUL)); }
protected override Response HandleCommand(Command cmd) { //Console.WriteLine(cmd.Raw); Response response = null; FtpLogEntry logEntry = new FtpLogEntry { Date = DateTime.Now, CIP = ClientIP, CSArgs = cmd.RawArguments }; ConnectionInfo.LastCommand = cmd.Code; //请求的命令需要权限 if (!_validCommands.Contains(cmd.Code)) { response = CheckUser(); //如果被拒绝将直接发送权限认证的响应 } // RNFR重命名后面必须立即接RNTO命令 if (cmd.Code != "RNTO") { _renameFrom = null; } // REST重新开始后面必须立即接传输命令 if (cmd.Code != "RETR" && cmd.Code != "STOR") { _transPosition = 0; } if (response == null) { switch (cmd.Code) { case "USER": //用户名 response = User(cmd.Arguments.FirstOrDefault()); break; case "PASS": //密码 response = Password(cmd.Arguments.FirstOrDefault()); logEntry.CSArgs = "******"; break; case "CWD": //切换目录 response = ChangeWorkingDirectory(cmd.RawArguments); break; case "CDUP": //切换到上级目录 response = ChangeWorkingDirectory(".."); break; case "QUIT": //退出 if (((FtpServer)CurrentServer).Config.LogOutWelcome != null) { Write(new Response { Code = "221-", Text = "Logging Out" }); foreach (var welcome in ((FtpServer)CurrentServer).Config.LogOutWelcome) { Write(new Response { Code = "", Text = welcome }); } } response = GetResponse(FtpResponses.QUIT); break; case "REIN": //初始化 _currentUser = null; _username = null; _dataClient = null; _currentCulture = CultureInfo.CurrentCulture; _currentEncoding = Encoding.ASCII; ControlStreamEncoding = Encoding.ASCII; response = GetResponse(FtpResponses.SERVICE_READY); break; case "PORT": //主动模式设置端口 response = Port(cmd.RawArguments); logEntry.CPort = _dataEndpoint.Port.ToString(CultureInfo.InvariantCulture); break; case "PASV": //进入被动模式 response = Passive(); logEntry.SPort = ((IPEndPoint)_passiveListener.LocalEndpoint).Port.ToString(CultureInfo.InvariantCulture); break; case "TYPE": //设置传输类型 response = Type(cmd.Arguments.FirstOrDefault(), cmd.Arguments.Skip(1).FirstOrDefault()); break; case "STRU": //设置结构 response = Structure(cmd.Arguments.FirstOrDefault()); break; case "MODE": //设置模式 response = Mode(cmd.Arguments.FirstOrDefault()); break; case "RNFR": //重命名 _renameFrom = cmd.RawArguments; response = GetResponse(FtpResponses.RENAME_FROM); break; case "RNTO": //重命名为 response = Rename(_renameFrom, cmd.RawArguments); break; case "DELE": //删除文件 response = Delete(cmd.RawArguments); break; case "RMD": //删除文件夹 response = RemoveDir(cmd.RawArguments); break; case "MKD": //建立文件夹 response = CreateDir(cmd.RawArguments); break; case "PWD": //显示目录 response = PrintWorkingDirectory(); break; case "RETR": //下载文件 //FIXED:文件名含空格 response = Retrieve(cmd.RawArguments); logEntry.Date = DateTime.Now; break; case "STOR": //上传文件 response = Store(cmd.RawArguments); logEntry.Date = DateTime.Now; break; case "STOU": //上传文件(不覆盖现有文件) response = StoreUnique(cmd.RawArguments); logEntry.Date = DateTime.Now; break; case "APPE": //追加 response = Append(cmd.RawArguments); logEntry.Date = DateTime.Now; break; case "LIST": //列出目录文件 response = List(cmd.RawArguments); logEntry.Date = DateTime.Now; break; case "SYST": //系统类型 response = GetResponse(FtpResponses.SYSTEM); break; case "NOOP": //空指令 只为获取服务器响应 response = GetResponse(FtpResponses.OK); break; case "ACCT": //要求账户(未实现) response = Account(cmd.RawArguments); break; case "ALLO": //分配 (对于不需要分配存储空间的机器,它的作用等于NOOP) response = GetResponse(FtpResponses.OK); break; case "NLST": //列文件名 response = NameList(cmd.RawArguments); break; case "SITE": //服务器系统相关命令 //TODO:可能在此处加入搜索 response = GetResponse(FtpResponses.NOT_IMPLEMENTED); break; case "STAT": response = GetResponse(FtpResponses.NOT_IMPLEMENTED); break; case "HELP": //帮助 response = GetResponse(FtpResponses.NOT_IMPLEMENTED); break; case "SMNT": response = GetResponse(FtpResponses.NOT_IMPLEMENTED); break; case "REST": //重新开始 //ADDED:尝试断点续传 response = Restart(cmd.RawArguments); break; case "ABOR": //中断传输,关闭数据连接 response = GetResponse(FtpResponses.NOT_IMPLEMENTED); break; // Extensions defined by rfc 2228 case "AUTH": //权限验证 AUTH <验证方法> response = Auth(cmd.RawArguments); break; case "PBSZ": //设置保护缓冲区大小,在SSL/TLS中永远是0 response = ProtectBufferSize(cmd.RawArguments); break; case "PROT": //保护级别 response = ProtectionLevel(cmd.Arguments.FirstOrDefault()); break; // Extensions defined by rfc 2389 case "FEAT": //显示扩展指令 response = GetResponse(FtpResponses.FEATURES); break; case "OPTS": //参数设置 response = Options(cmd.Arguments); break; // Extensions defined by rfc 3659 case "MDTM": //回显文件修改时间,通常用于对时 response = FileModificationTime(cmd.RawArguments); //FIXED:只接受一个参数的 务必使用RawArg break; case "SIZE": //回显文件大小 response = FileSize(cmd.RawArguments); break; case "MLSD": //标准格式列目录 response = MachineListDirectory(cmd.RawArguments); break; case "MLST": //标准格式列文件信息 response = MachineListTime(cmd.RawArguments); break; // Extensions defined by rfc 2428 case "EPRT": //扩展主动模式(IPv6) response = EPort(cmd.RawArguments); logEntry.CPort = _dataEndpoint.Port.ToString(CultureInfo.InvariantCulture); break; case "EPSV": //扩展被动动模式(IPv6) response = EPassive(); logEntry.SPort = ((IPEndPoint)_passiveListener.LocalEndpoint).Port.ToString(CultureInfo.InvariantCulture); break; // Extensions defined by rfc 2640 case "LANG": //切换服务端显示语言 response = Language(cmd.Arguments.FirstOrDefault()); break; default: response = GetResponse(FtpResponses.NOT_IMPLEMENTED); break; } } logEntry.CSMethod = cmd.Code; logEntry.CSUsername = _username; logEntry.SCStatus = response.Code; _log.Info(logEntry); OnLog(logEntry); _lastCommand = cmd; return(response); }