<PackageReference Include="SSH.NET" Version="2023.0.1" />

SftpClient

Implementation of the SSH File Transfer Protocol (SFTP) over SSH.
using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Sftp; using Renci.SshNet.Sftp.Responses; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Renci.SshNet { public class SftpClient : BaseClient, ISftpClient, IBaseClient, IDisposable { private static readonly Encoding Utf8NoBOM = new UTF8Encoding(false, true); private ISftpSession _sftpSession; private int _operationTimeout; private uint _bufferSize; public TimeSpan OperationTimeout { get { CheckDisposed(); return TimeSpan.FromMilliseconds((double)_operationTimeout); } set { CheckDisposed(); double totalMilliseconds = value.TotalMilliseconds; if ((totalMilliseconds < -1 || totalMilliseconds > 2147483647) ? true : false) throw new ArgumentOutOfRangeException("value", "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); _operationTimeout = (int)totalMilliseconds; } } public uint BufferSize { get { CheckDisposed(); return _bufferSize; } set { CheckDisposed(); _bufferSize = value; } } public string WorkingDirectory { get { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); return _sftpSession.WorkingDirectory; } } public int ProtocolVersion { get { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); return (int)_sftpSession.ProtocolVersion; } } internal ISftpSession SftpSession => _sftpSession; public SftpClient(ConnectionInfo connectionInfo) : this(connectionInfo, false) { } public SftpClient(string host, int port, string username, string password) : this(new PasswordConnectionInfo(host, port, username, password), true) { } public SftpClient(string host, string username, string password) : this(host, 22, username, password) { } public SftpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } public SftpClient(string host, string username, params IPrivateKeySource[] keyFiles) : this(host, 22, username, keyFiles) { } private SftpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo) : this(connectionInfo, ownsConnectionInfo, new ServiceFactory()) { } internal SftpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServiceFactory serviceFactory) : base(connectionInfo, ownsConnectionInfo, serviceFactory) { _operationTimeout = -1; _bufferSize = 32768; } public void ChangeDirectory(string path) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); _sftpSession.ChangeDirectory(path); } public void ChangePermissions(string path, short mode) { Get(path).SetPermissions(mode); } public void CreateDirectory(string path) { CheckDisposed(); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(path); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestMkDir(canonicalPath); } public void DeleteDirectory(string path) { CheckDisposed(); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestRmDir(canonicalPath); } public void DeleteFile(string path) { CheckDisposed(); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestRemove(canonicalPath); } [AsyncStateMachine(typeof(<DeleteFileAsync>d__28))] public Task DeleteFileAsync(string path, CancellationToken cancellationToken) { <DeleteFileAsync>d__28 stateMachine = default(<DeleteFileAsync>d__28); stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.path = path; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public void RenameFile(string oldPath, string newPath) { RenameFile(oldPath, newPath, false); } public void RenameFile(string oldPath, string newPath, bool isPosix) { CheckDisposed(); if (oldPath == null) throw new ArgumentNullException("oldPath"); if (newPath == null) throw new ArgumentNullException("newPath"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(oldPath); string canonicalPath2 = _sftpSession.GetCanonicalPath(newPath); if (isPosix) _sftpSession.RequestPosixRename(canonicalPath, canonicalPath2); else _sftpSession.RequestRename(canonicalPath, canonicalPath2); } [AsyncStateMachine(typeof(<RenameFileAsync>d__31))] public Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken) { <RenameFileAsync>d__31 stateMachine = default(<RenameFileAsync>d__31); stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.oldPath = oldPath; stateMachine.newPath = newPath; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public void SymbolicLink(string path, string linkPath) { CheckDisposed(); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (string.IsNullOrWhiteSpace(linkPath)) throw new ArgumentException("linkPath"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); string canonicalPath2 = _sftpSession.GetCanonicalPath(linkPath); _sftpSession.RequestSymLink(canonicalPath, canonicalPath2); } public IEnumerable<ISftpFile> ListDirectory(string path, Action<int> listCallback = null) { CheckDisposed(); return InternalListDirectory(path, null, listCallback); } [AsyncIteratorStateMachine(typeof(<ListDirectoryAsync>d__34))] public IAsyncEnumerable<ISftpFile> ListDirectoryAsync(string path, [EnumeratorCancellation] CancellationToken cancellationToken) { <ListDirectoryAsync>d__34 <ListDirectoryAsync>d__ = new <ListDirectoryAsync>d__34(-2); <ListDirectoryAsync>d__.<>4__this = this; <ListDirectoryAsync>d__.<>3__path = path; <ListDirectoryAsync>d__.<>3__cancellationToken = cancellationToken; return <ListDirectoryAsync>d__; } public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state, Action<int> listCallback = null) { CheckDisposed(); SftpListDirectoryAsyncResult asyncResult = new SftpListDirectoryAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { List<ISftpFile> result = InternalListDirectory(path, asyncResult, listCallback); asyncResult.SetAsCompleted(result, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public IEnumerable<ISftpFile> EndListDirectory(IAsyncResult asyncResult) { SftpListDirectoryAsyncResult sftpListDirectoryAsyncResult = asyncResult as SftpListDirectoryAsyncResult; if (sftpListDirectoryAsyncResult == null || sftpListDirectoryAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); return sftpListDirectoryAsyncResult.EndInvoke(); } public ISftpFile Get(string path) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); SftpFileAttributes attributes = _sftpSession.RequestLStat(canonicalPath); return new SftpFile(_sftpSession, canonicalPath, attributes); } public bool Exists(string path) { CheckDisposed(); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (_sftpSession != null) { string canonicalPath = _sftpSession.GetCanonicalPath(path); try { _sftpSession.RequestLStat(canonicalPath); return true; } catch (SftpPathNotFoundException) { return false; } } throw new SshConnectionException("Client not connected."); } public void DownloadFile(string path, Stream output, Action<ulong> downloadCallback = null) { CheckDisposed(); InternalDownloadFile(path, output, null, downloadCallback); } public IAsyncResult BeginDownloadFile(string path, Stream output) { return BeginDownloadFile(path, output, null, null, null); } public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback) { return BeginDownloadFile(path, output, asyncCallback, null, null); } public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback, object state, Action<ulong> downloadCallback = null) { CheckDisposed(); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (output == null) throw new ArgumentNullException("output"); SftpDownloadAsyncResult asyncResult = new SftpDownloadAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { InternalDownloadFile(path, output, asyncResult, downloadCallback); asyncResult.SetAsCompleted(null, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public void EndDownloadFile(IAsyncResult asyncResult) { SftpDownloadAsyncResult sftpDownloadAsyncResult = asyncResult as SftpDownloadAsyncResult; if (sftpDownloadAsyncResult == null || sftpDownloadAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); sftpDownloadAsyncResult.EndInvoke(); } public void UploadFile(Stream input, string path, Action<ulong> uploadCallback = null) { UploadFile(input, path, true, uploadCallback); } public void UploadFile(Stream input, string path, bool canOverride, Action<ulong> uploadCallback = null) { CheckDisposed(); Flags flags = Flags.Write | Flags.Truncate; flags = ((!canOverride) ? (flags | Flags.CreateNew) : (flags | Flags.CreateNewOrOpen)); InternalUploadFile(input, path, flags, null, uploadCallback); } public IAsyncResult BeginUploadFile(Stream input, string path) { return BeginUploadFile(input, path, true, null, null, null); } public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback) { return BeginUploadFile(input, path, true, asyncCallback, null, null); } public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null) { return BeginUploadFile(input, path, true, asyncCallback, state, uploadCallback); } public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null) { CheckDisposed(); if (input == null) throw new ArgumentNullException("input"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); Flags flags = Flags.Write | Flags.Truncate; if (canOverride) flags |= Flags.CreateNewOrOpen; else flags |= Flags.CreateNew; SftpUploadAsyncResult asyncResult = new SftpUploadAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { InternalUploadFile(input, path, flags, asyncResult, uploadCallback); asyncResult.SetAsCompleted(null, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public void EndUploadFile(IAsyncResult asyncResult) { SftpUploadAsyncResult sftpUploadAsyncResult = asyncResult as SftpUploadAsyncResult; if (sftpUploadAsyncResult == null || sftpUploadAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); sftpUploadAsyncResult.EndInvoke(); } public SftpFileSytemInformation GetStatus(string path) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); return _sftpSession.RequestStatVfs(canonicalPath, false); } [AsyncStateMachine(typeof(<GetStatusAsync>d__52))] public Task<SftpFileSytemInformation> GetStatusAsync(string path, CancellationToken cancellationToken) { <GetStatusAsync>d__52 stateMachine = default(<GetStatusAsync>d__52); stateMachine.<>t__builder = AsyncTaskMethodBuilder<SftpFileSytemInformation>.Create(); stateMachine.<>4__this = this; stateMachine.path = path; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public void AppendAllLines(string path, IEnumerable<string> contents) { CheckDisposed(); if (contents == null) throw new ArgumentNullException("contents"); using (StreamWriter streamWriter = AppendText(path)) { foreach (string content in contents) { streamWriter.WriteLine(content); } } } public void AppendAllLines(string path, IEnumerable<string> contents, Encoding encoding) { CheckDisposed(); if (contents == null) throw new ArgumentNullException("contents"); using (StreamWriter streamWriter = AppendText(path, encoding)) { foreach (string content in contents) { streamWriter.WriteLine(content); } } } public void AppendAllText(string path, string contents) { using (StreamWriter streamWriter = AppendText(path)) streamWriter.Write(contents); } public void AppendAllText(string path, string contents, Encoding encoding) { using (StreamWriter streamWriter = AppendText(path, encoding)) streamWriter.Write(contents); } public StreamWriter AppendText(string path) { return AppendText(path, Utf8NoBOM); } public StreamWriter AppendText(string path, Encoding encoding) { CheckDisposed(); if (encoding == null) throw new ArgumentNullException("encoding"); return new StreamWriter(new SftpFileStream(_sftpSession, path, FileMode.Append, FileAccess.Write, (int)_bufferSize), encoding); } public SftpFileStream Create(string path) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, FileMode.Create, FileAccess.ReadWrite, (int)_bufferSize); } public SftpFileStream Create(string path, int bufferSize) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, FileMode.Create, FileAccess.ReadWrite, bufferSize); } public StreamWriter CreateText(string path) { return CreateText(path, Utf8NoBOM); } public StreamWriter CreateText(string path, Encoding encoding) { CheckDisposed(); return new StreamWriter(OpenWrite(path), encoding); } public void Delete(string path) { Get(path).Delete(); } public DateTime GetLastAccessTime(string path) { return Get(path).LastAccessTime; } public DateTime GetLastAccessTimeUtc(string path) { return GetLastAccessTime(path).ToUniversalTime(); } public DateTime GetLastWriteTime(string path) { return Get(path).LastWriteTime; } public DateTime GetLastWriteTimeUtc(string path) { return GetLastWriteTime(path).ToUniversalTime(); } public SftpFileStream Open(string path, FileMode mode) { return Open(path, mode, FileAccess.ReadWrite); } public SftpFileStream Open(string path, FileMode mode, FileAccess access) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, mode, access, (int)_bufferSize); } public Task<SftpFileStream> OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); cancellationToken.ThrowIfCancellationRequested(); return SftpFileStream.OpenAsync(_sftpSession, path, mode, access, (int)_bufferSize, cancellationToken); } public SftpFileStream OpenRead(string path) { return Open(path, FileMode.Open, FileAccess.Read); } public StreamReader OpenText(string path) { return new StreamReader(OpenRead(path), Encoding.UTF8); } public SftpFileStream OpenWrite(string path) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, FileMode.OpenOrCreate, FileAccess.Write, (int)_bufferSize); } public byte[] ReadAllBytes(string path) { using (SftpFileStream sftpFileStream = OpenRead(path)) { byte[] array = new byte[sftpFileStream.Length]; sftpFileStream.Read(array, 0, array.Length); return array; } } public string[] ReadAllLines(string path) { return ReadAllLines(path, Encoding.UTF8); } public string[] ReadAllLines(string path, Encoding encoding) { List<string> list = new List<string>(); using (StreamReader streamReader = new StreamReader(OpenRead(path), encoding)) { while (!streamReader.EndOfStream) { list.Add(streamReader.ReadLine()); } } return list.ToArray(); } public string ReadAllText(string path) { return ReadAllText(path, Encoding.UTF8); } public string ReadAllText(string path, Encoding encoding) { using (StreamReader streamReader = new StreamReader(OpenRead(path), encoding)) return streamReader.ReadToEnd(); } public IEnumerable<string> ReadLines(string path) { return ReadAllLines(path); } public IEnumerable<string> ReadLines(string path, Encoding encoding) { return ReadAllLines(path, encoding); } public void SetLastAccessTime(string path, DateTime lastAccessTime) { SftpFileAttributes attributes = GetAttributes(path); attributes.LastAccessTime = lastAccessTime; SetAttributes(path, attributes); } public void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc) { SftpFileAttributes attributes = GetAttributes(path); attributes.LastAccessTimeUtc = lastAccessTimeUtc; SetAttributes(path, attributes); } public void SetLastWriteTime(string path, DateTime lastWriteTime) { SftpFileAttributes attributes = GetAttributes(path); attributes.LastWriteTime = lastWriteTime; SetAttributes(path, attributes); } public void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc) { SftpFileAttributes attributes = GetAttributes(path); attributes.LastWriteTimeUtc = lastWriteTimeUtc; SetAttributes(path, attributes); } public void WriteAllBytes(string path, byte[] bytes) { using (SftpFileStream sftpFileStream = OpenWrite(path)) sftpFileStream.Write(bytes, 0, bytes.Length); } public void WriteAllLines(string path, IEnumerable<string> contents) { WriteAllLines(path, contents, Utf8NoBOM); } public void WriteAllLines(string path, string[] contents) { WriteAllLines(path, contents, Utf8NoBOM); } public void WriteAllLines(string path, IEnumerable<string> contents, Encoding encoding) { using (StreamWriter streamWriter = CreateText(path, encoding)) { foreach (string content in contents) { streamWriter.WriteLine(content); } } } public void WriteAllLines(string path, string[] contents, Encoding encoding) { using (StreamWriter streamWriter = CreateText(path, encoding)) { foreach (string value in contents) { streamWriter.WriteLine(value); } } } public void WriteAllText(string path, string contents) { using (StreamWriter streamWriter = CreateText(path)) streamWriter.Write(contents); } public void WriteAllText(string path, string contents, Encoding encoding) { using (StreamWriter streamWriter = CreateText(path, encoding)) streamWriter.Write(contents); } public SftpFileAttributes GetAttributes(string path) { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); return _sftpSession.RequestLStat(canonicalPath); } public void SetAttributes(string path, SftpFileAttributes fileAttributes) { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestSetStat(canonicalPath, fileAttributes); } public IEnumerable<FileInfo> SynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern) { if (sourcePath == null) throw new ArgumentNullException("sourcePath"); if (string.IsNullOrWhiteSpace(destinationPath)) throw new ArgumentException("destinationPath"); return InternalSynchronizeDirectories(sourcePath, destinationPath, searchPattern, null); } public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state) { if (sourcePath == null) throw new ArgumentNullException("sourcePath"); if (string.IsNullOrWhiteSpace(destinationPath)) throw new ArgumentException("destDir"); SftpSynchronizeDirectoriesAsyncResult asyncResult = new SftpSynchronizeDirectoriesAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { List<FileInfo> result = InternalSynchronizeDirectories(sourcePath, destinationPath, searchPattern, asyncResult); asyncResult.SetAsCompleted(result, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public IEnumerable<FileInfo> EndSynchronizeDirectories(IAsyncResult asyncResult) { SftpSynchronizeDirectoriesAsyncResult sftpSynchronizeDirectoriesAsyncResult = asyncResult as SftpSynchronizeDirectoriesAsyncResult; if (sftpSynchronizeDirectoriesAsyncResult == null || sftpSynchronizeDirectoriesAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); return sftpSynchronizeDirectoriesAsyncResult.EndInvoke(); } private List<FileInfo> InternalSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, SftpSynchronizeDirectoriesAsyncResult asynchResult) { if (!Directory.Exists(sourcePath)) throw new FileNotFoundException($"""{sourcePath}"); List<FileInfo> list = new List<FileInfo>(); using (IEnumerator<FileInfo> enumerator = new DirectoryInfo(sourcePath).EnumerateFiles(searchPattern).GetEnumerator()) { if (enumerator.MoveNext()) { List<ISftpFile> list2 = InternalListDirectory(destinationPath, null, null); Dictionary<string, ISftpFile> dictionary = new Dictionary<string, ISftpFile>(); foreach (ISftpFile item in list2) { if (!item.IsDirectory) dictionary.Add(item.Name, item); } do { FileInfo current2 = enumerator.Current; if (current2 != null) { bool flag = true; if (dictionary.TryGetValue(current2.Name, out ISftpFile value)) flag = (current2.Length != value.Length); if (flag) { string text = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", destinationPath, current2.Name); try { using (FileStream input = File.OpenRead(current2.FullName)) InternalUploadFile(input, text, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, null, null); list.Add(current2); asynchResult?.Update(list.Count); } catch (Exception inner) { throw new SshException("Failed to upload " + current2.FullName + " to " + text, inner); } } } } while (enumerator.MoveNext()); return list; } return list; } } private List<ISftpFile> InternalListDirectory(string path, SftpListDirectoryAsyncResult asyncResult, Action<int> listCallback) { if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); byte[] handle = _sftpSession.RequestOpenDir(canonicalPath, false); string text = canonicalPath; if (!text.EndsWith("/", StringComparison.Ordinal)) text = $"{canonicalPath}"""; List<ISftpFile> result = new List<ISftpFile>(); for (KeyValuePair<string, SftpFileAttributes>[] array = _sftpSession.RequestReadDir(handle); array != null; array = _sftpSession.RequestReadDir(handle)) { KeyValuePair<string, SftpFileAttributes>[] array2 = array; for (int i = 0; i < array2.Length; i++) { KeyValuePair<string, SftpFileAttributes> keyValuePair = array2[i]; result.Add(new SftpFile(_sftpSession, string.Format(CultureInfo.InvariantCulture, "{0}{1}", text, keyValuePair.Key), keyValuePair.Value)); } asyncResult?.Update(result.Count); if (listCallback != null) ThreadAbstraction.ExecuteThread(delegate { listCallback(result.Count); }); } _sftpSession.RequestClose(handle); return result; } private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncResult asyncResult, Action<ulong> downloadCallback) { if (output == null) throw new ArgumentNullException("output"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); using (ISftpFileReader sftpFileReader = base.ServiceFactory.CreateSftpFileReader(canonicalPath, _sftpSession, _bufferSize)) { ulong num = 0; while (asyncResult == null || !asyncResult.IsDownloadCanceled) { byte[] array = sftpFileReader.Read(); if (array.Length == 0) break; output.Write(array, 0, array.Length); num = (ulong)((long)num + (long)array.Length); asyncResult?.Update(num); if (downloadCallback != null) { ulong downloadOffset = num; ThreadAbstraction.ExecuteThread(delegate { downloadCallback(downloadOffset); }); } } } } private void InternalUploadFile(Stream input, string path, Flags flags, SftpUploadAsyncResult asyncResult, Action<ulong> uploadCallback) { if (input == null) throw new ArgumentNullException("input"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); byte[] handle = _sftpSession.RequestOpen(canonicalPath, flags, false); ulong num = 0; byte[] array = new byte[_sftpSession.CalculateOptimalWriteLength(_bufferSize, handle)]; int num2 = input.Read(array, 0, array.Length); int expectedResponses = 0; AutoResetEvent responseReceivedWaitHandle = new AutoResetEvent(false); while (asyncResult == null || !asyncResult.IsUploadCanceled) { if (num2 > 0) { ulong writtenBytes = (ulong)((long)num + (long)num2); _sftpSession.RequestWrite(handle, num, array, 0, num2, null, delegate(SftpStatusResponse s) { if (s.StatusCode == StatusCodes.Ok) { Interlocked.Decrement(ref expectedResponses); responseReceivedWaitHandle.Set(); asyncResult?.Update(writtenBytes); if (uploadCallback != null) ThreadAbstraction.ExecuteThread(delegate { uploadCallback(writtenBytes); }); } }); Interlocked.Increment(ref expectedResponses); num = (ulong)((long)num + (long)num2); num2 = input.Read(array, 0, array.Length); } else if (expectedResponses > 0) { _sftpSession.WaitOnHandle(responseReceivedWaitHandle, _operationTimeout); } if (expectedResponses <= 0 && num2 <= 0) break; } _sftpSession.RequestClose(handle); responseReceivedWaitHandle.Dispose(); } protected override void OnConnected() { base.OnConnected(); _sftpSession = CreateAndConnectToSftpSession(); } protected override void OnDisconnecting() { base.OnDisconnecting(); ISftpSession sftpSession = _sftpSession; if (sftpSession != null) { _sftpSession = null; sftpSession.Dispose(); } } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { ISftpSession sftpSession = _sftpSession; if (sftpSession != null) { _sftpSession = null; sftpSession.Dispose(); } } } private ISftpSession CreateAndConnectToSftpSession() { ISftpSession sftpSession = base.ServiceFactory.CreateSftpSession(base.Session, _operationTimeout, base.ConnectionInfo.Encoding, base.ServiceFactory.CreateSftpResponseFactory()); try { sftpSession.Connect(); return sftpSession; } catch { sftpSession.Dispose(); throw; } } } }