private async Task <bool> ChangeWorkingDirectoryAsync(ComplexSocket controlComplexSocket, string directory, CancellationToken cancellationToken, bool createDirectoryIfNotExists = false) { var success = await this.SendAndLogAsync(controlComplexSocket, cancellationToken, "CWD {0}", directory); if (!success) { return(false); } var ftpReply = await this.ReceiveAndLogAsync(controlComplexSocket, cancellationToken); switch (ftpReply.FtpResponseType) { case FtpResponseType.PermanentNegativeCompletion: // TODO some parsing of the actual FtpReply.ResponseCode should be done in here. i assume 5xx-state means "directory does not exist" all the time, which might be wrong if (!createDirectoryIfNotExists) { return(false); } success = await this.SendAndLogAsync(controlComplexSocket, cancellationToken, "MKD {0}", directory); if (!success) { return(false); } ftpReply = await this.ReceiveAndLogAsync(controlComplexSocket, cancellationToken); if (!ftpReply.Success) { return(false); } goto case FtpResponseType.PositiveCompletion; case FtpResponseType.PositiveCompletion: this._currentFtpDirectory = FtpDirectory.Create(this._currentFtpDirectory, directory); break; default: return(false); } return(true); }
public async Task <bool> CreateDirectoryAsync(string path, CancellationToken cancellationToken) { using (await this._mutex.LockAsync()) { var controlComplexSocket = await this.EnsureConnectionAndAuthenticationAsync(cancellationToken); if (controlComplexSocket == null) { return(false); } var ftpDirectory = FtpDirectory.Create(path); var success = await this.GotoParentDirectoryAsync(controlComplexSocket, ftpDirectory, cancellationToken, true); return(success); } }
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); }