public async Task <IEnumerable <FtpListItem> > GetListingAsync(string path, CancellationToken cancellationToken) { IEnumerable <string> rawListing; FtpListType ftpListType; using (await this._mutex.LockAsync(cancellationToken)) { var controlComplexSocket = await this.EnsureConnectionAndAuthenticationAsync(cancellationToken); if (controlComplexSocket == null) { return(Enumerable.Empty <FtpListItem>()); } string command; var ftpFeatures = await this.GetFtpFeaturesAsync(controlComplexSocket, cancellationToken); if (ftpFeatures.HasFlag(FtpFeatures.MLSD)) { ftpListType = FtpListType.MLSD; command = "MLSD"; } else if (ftpFeatures.HasFlag(FtpFeatures.MLST)) { ftpListType = FtpListType.MLST; command = "MLST"; } else { ftpListType = FtpListType.LIST; command = "LIST"; } var ftpDirectory = FtpDirectory.Create(path); { var success = await this.GotoParentDirectoryAsync(controlComplexSocket, ftpDirectory, cancellationToken); if (!success) { return(Enumerable.Empty <FtpListItem>()); } } if (!string.IsNullOrEmpty(ftpDirectory.DirectoryName)) { var success = await this.ChangeWorkingDirectoryAsync(controlComplexSocket, ftpDirectory.DirectoryName, cancellationToken); if (!success) { return(Enumerable.Empty <FtpListItem>()); } } { // sending PASV // reading PASV var transferComplexSocket = await this.GetPassiveComplexSocketAsync(controlComplexSocket, cancellationToken); if (transferComplexSocket == null) { return(Enumerable.Empty <FtpListItem>()); } FtpReply ftpReply; using (transferComplexSocket) { // sending LIST/... // open PASV // reading LIST/... (150 Here comes the directory listing) var success = await this.SendAndLogAsync(controlComplexSocket, cancellationToken, command); if (!success) { return(Enumerable.Empty <FtpListItem>()); } success = await transferComplexSocket.ConnectAsync(cancellationToken); if (!success) { return(Enumerable.Empty <FtpListItem>()); } ftpReply = await this.ReceiveAndLogAsync(controlComplexSocket, cancellationToken); if (!ftpReply.Success) { return(Enumerable.Empty <FtpListItem>()); } { this.WaitBeforeReceive(); // reading transfer var receiveResult = await transferComplexSocket.Socket.ReceiveAsync(this.ChunkReceiveBufferSize, transferComplexSocket.GetSocketAsyncEventArgs, this.Encoding, cancellationToken); if (!receiveResult.Success) { return(Enumerable.Empty <FtpListItem>()); } rawListing = (receiveResult.Data ?? string.Empty).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); } } if (!ftpReply.Completed) { // reading LIST/... (226 Directory send OK) ftpReply = await this.ReceiveAndLogAsync(controlComplexSocket, cancellationToken); if (!ftpReply.Success) { return(Enumerable.Empty <FtpListItem>()); } } } } var ftpListItems = FtpListItem.ParseList(rawListing, ftpListType); return(ftpListItems); }
public IEnumerable <FtpListItem> GetListing(string path) { IEnumerable <string> rawListing; FtpListType ftpListType; lock (this._lockControlComplexSocket) { { var success = this.EnsureConnection(); if (!success) { return(Enumerable.Empty <FtpListItem>()); } } string command; if (this.FtpFeatures.HasFlag(FtpFeatures.MLSD)) { ftpListType = FtpListType.MLSD; command = "MLSD"; } else if (this.FtpFeatures.HasFlag(FtpFeatures.MLST)) { ftpListType = FtpListType.MLST; command = "MLST"; } else { // TODO check if really *always* available ftpListType = FtpListType.LIST; command = "LIST"; } var concreteCommand = string.Format("{0} {1}", command, path); var controlComplexSocket = this._controlComplexSocket; if (this.FtpFeatures.HasFlag(FtpFeatures.PRET)) { // On servers that advertise PRET (DrFTPD), the PRET command must be executed before a passive connection is opened. { var success = controlComplexSocket.Send(string.Format("PRET {0}", concreteCommand), this.Encoding, this.SendTimeout); if (!success) { return(Enumerable.Empty <FtpListItem>()); } } { var complexResult = controlComplexSocket.Receive(this.Encoding, this.ReceiveTimeout); var success = complexResult.Success; if (!success) { return(Enumerable.Empty <FtpListItem>()); } } } { var transferComplexSocket = this.GetPassiveComplexSocket(); if (transferComplexSocket == null) { return(Enumerable.Empty <FtpListItem>()); } using (transferComplexSocket) { { // send LIST/MLSD/MLST-command via control socket { var success = controlComplexSocket.Send(concreteCommand, this.Encoding, this.SendTimeout); if (!success) { return(Enumerable.Empty <FtpListItem>()); } } { var complexResult = controlComplexSocket.Receive(this.Encoding, this.ReceiveTimeout); var success = complexResult.Success; if (!success) { return(Enumerable.Empty <FtpListItem>()); } } } { // receive listing via transfer socket var connected = transferComplexSocket.Connect(this.ConnectTimeout); if (!connected) { return(Enumerable.Empty <FtpListItem>()); } var complexResult = transferComplexSocket.Receive(this.Encoding, this.ReceiveTimeout); // TODO check if there's a need to check against FtpReply.Success or anything alike! rawListing = complexResult.Messages; } } } } var ftpListItems = FtpListItem.ParseList(rawListing, ftpListType); return(ftpListItems); }