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