|
@@ -1,5 +1,7 @@
|
|
|
-using System;
|
|
|
|
|
|
|
+#nullable enable
|
|
|
|
|
+using System;
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
|
|
|
+using System.Diagnostics;
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
using System.Globalization;
|
|
using System.Globalization;
|
|
|
using System.IO;
|
|
using System.IO;
|
|
@@ -127,12 +129,12 @@ namespace Renci.SshNet
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Occurs when downloading file.
|
|
/// Occurs when downloading file.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public event EventHandler<ScpDownloadEventArgs> Downloading;
|
|
|
|
|
|
|
+ public event EventHandler<ScpDownloadEventArgs>? Downloading;
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Occurs when uploading file.
|
|
/// Occurs when uploading file.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public event EventHandler<ScpUploadEventArgs> Uploading;
|
|
|
|
|
|
|
+ public event EventHandler<ScpUploadEventArgs>? Uploading;
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Initializes a new instance of the <see cref="ScpClient"/> class.
|
|
/// Initializes a new instance of the <see cref="ScpClient"/> class.
|
|
@@ -246,8 +248,14 @@ namespace Renci.SshNet
|
|
|
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length <see cref="string"/>.</exception>
|
|
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length <see cref="string"/>.</exception>
|
|
|
/// <exception cref="ScpException">A directory with the specified path exists on the remote host.</exception>
|
|
/// <exception cref="ScpException">A directory with the specified path exists on the remote host.</exception>
|
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
|
|
|
+ /// <exception cref="SshConnectionException">Client is not connected.</exception>
|
|
|
public void Upload(Stream source, string path)
|
|
public void Upload(Stream source, string path)
|
|
|
{
|
|
{
|
|
|
|
|
+ if (Session is null)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw new SshConnectionException("Client not connected.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var posixPath = PosixPath.CreateAbsoluteOrRelativeFilePath(path);
|
|
var posixPath = PosixPath.CreateAbsoluteOrRelativeFilePath(path);
|
|
|
|
|
|
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
@@ -280,6 +288,7 @@ namespace Renci.SshNet
|
|
|
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length <see cref="string"/>.</exception>
|
|
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length <see cref="string"/>.</exception>
|
|
|
/// <exception cref="ScpException">A directory with the specified path exists on the remote host.</exception>
|
|
/// <exception cref="ScpException">A directory with the specified path exists on the remote host.</exception>
|
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
|
|
|
+ /// <exception cref="SshConnectionException">Client is not connected.</exception>
|
|
|
public void Upload(FileInfo fileInfo, string path)
|
|
public void Upload(FileInfo fileInfo, string path)
|
|
|
{
|
|
{
|
|
|
if (fileInfo is null)
|
|
if (fileInfo is null)
|
|
@@ -287,6 +296,11 @@ namespace Renci.SshNet
|
|
|
throw new ArgumentNullException(nameof(fileInfo));
|
|
throw new ArgumentNullException(nameof(fileInfo));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (Session is null)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw new SshConnectionException("Client not connected.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var posixPath = PosixPath.CreateAbsoluteOrRelativeFilePath(path);
|
|
var posixPath = PosixPath.CreateAbsoluteOrRelativeFilePath(path);
|
|
|
|
|
|
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
@@ -323,6 +337,7 @@ namespace Renci.SshNet
|
|
|
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length string.</exception>
|
|
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length string.</exception>
|
|
|
/// <exception cref="ScpException"><paramref name="path"/> does not exist on the remote host, is not a directory or the user does not have the required permission.</exception>
|
|
/// <exception cref="ScpException"><paramref name="path"/> does not exist on the remote host, is not a directory or the user does not have the required permission.</exception>
|
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
|
|
|
+ /// <exception cref="SshConnectionException">Client is not connected.</exception>
|
|
|
public void Upload(DirectoryInfo directoryInfo, string path)
|
|
public void Upload(DirectoryInfo directoryInfo, string path)
|
|
|
{
|
|
{
|
|
|
if (directoryInfo is null)
|
|
if (directoryInfo is null)
|
|
@@ -340,6 +355,11 @@ namespace Renci.SshNet
|
|
|
throw new ArgumentException("The path cannot be a zero-length string.", nameof(path));
|
|
throw new ArgumentException("The path cannot be a zero-length string.", nameof(path));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (Session is null)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw new SshConnectionException("Client not connected.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
|
using (var channel = Session.CreateChannelSession())
|
|
using (var channel = Session.CreateChannelSession())
|
|
|
{
|
|
{
|
|
@@ -371,6 +391,7 @@ namespace Renci.SshNet
|
|
|
/// <exception cref="ArgumentException"><paramref name="filename"/> is <see langword="null"/> or empty.</exception>
|
|
/// <exception cref="ArgumentException"><paramref name="filename"/> is <see langword="null"/> or empty.</exception>
|
|
|
/// <exception cref="ScpException"><paramref name="filename"/> exists on the remote host, and is not a regular file.</exception>
|
|
/// <exception cref="ScpException"><paramref name="filename"/> exists on the remote host, and is not a regular file.</exception>
|
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
|
|
|
+ /// <exception cref="SshConnectionException">Client is not connected.</exception>
|
|
|
public void Download(string filename, FileInfo fileInfo)
|
|
public void Download(string filename, FileInfo fileInfo)
|
|
|
{
|
|
{
|
|
|
if (string.IsNullOrEmpty(filename))
|
|
if (string.IsNullOrEmpty(filename))
|
|
@@ -383,6 +404,11 @@ namespace Renci.SshNet
|
|
|
throw new ArgumentNullException(nameof(fileInfo));
|
|
throw new ArgumentNullException(nameof(fileInfo));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (Session is null)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw new SshConnectionException("Client not connected.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
|
using (var channel = Session.CreateChannelSession())
|
|
using (var channel = Session.CreateChannelSession())
|
|
|
{
|
|
{
|
|
@@ -411,6 +437,7 @@ namespace Renci.SshNet
|
|
|
/// <exception cref="ArgumentNullException"><paramref name="directoryInfo"/> is <see langword="null"/>.</exception>
|
|
/// <exception cref="ArgumentNullException"><paramref name="directoryInfo"/> is <see langword="null"/>.</exception>
|
|
|
/// <exception cref="ScpException">File or directory with the specified path does not exist on the remote host.</exception>
|
|
/// <exception cref="ScpException">File or directory with the specified path does not exist on the remote host.</exception>
|
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
|
|
|
+ /// <exception cref="SshConnectionException">Client is not connected.</exception>
|
|
|
public void Download(string directoryName, DirectoryInfo directoryInfo)
|
|
public void Download(string directoryName, DirectoryInfo directoryInfo)
|
|
|
{
|
|
{
|
|
|
if (string.IsNullOrEmpty(directoryName))
|
|
if (string.IsNullOrEmpty(directoryName))
|
|
@@ -423,6 +450,11 @@ namespace Renci.SshNet
|
|
|
throw new ArgumentNullException(nameof(directoryInfo));
|
|
throw new ArgumentNullException(nameof(directoryInfo));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (Session is null)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw new SshConnectionException("Client not connected.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
|
using (var channel = Session.CreateChannelSession())
|
|
using (var channel = Session.CreateChannelSession())
|
|
|
{
|
|
{
|
|
@@ -451,6 +483,7 @@ namespace Renci.SshNet
|
|
|
/// <exception cref="ArgumentNullException"><paramref name="destination"/> is <see langword="null"/>.</exception>
|
|
/// <exception cref="ArgumentNullException"><paramref name="destination"/> is <see langword="null"/>.</exception>
|
|
|
/// <exception cref="ScpException"><paramref name="filename"/> exists on the remote host, and is not a regular file.</exception>
|
|
/// <exception cref="ScpException"><paramref name="filename"/> exists on the remote host, and is not a regular file.</exception>
|
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
|
|
|
|
|
+ /// <exception cref="SshConnectionException">Client is not connected.</exception>
|
|
|
public void Download(string filename, Stream destination)
|
|
public void Download(string filename, Stream destination)
|
|
|
{
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(filename))
|
|
if (string.IsNullOrWhiteSpace(filename))
|
|
@@ -463,6 +496,11 @@ namespace Renci.SshNet
|
|
|
throw new ArgumentNullException(nameof(destination));
|
|
throw new ArgumentNullException(nameof(destination));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (Session is null)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw new SshConnectionException("Client not connected.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
using (var input = ServiceFactory.CreatePipeStream())
|
|
|
using (var channel = Session.CreateChannelSession())
|
|
using (var channel = Session.CreateChannelSession())
|
|
|
{
|
|
{
|
|
@@ -767,13 +805,17 @@ namespace Renci.SshNet
|
|
|
|
|
|
|
|
directoryCounter--;
|
|
directoryCounter--;
|
|
|
|
|
|
|
|
- currentDirectoryFullName = new DirectoryInfo(currentDirectoryFullName).Parent.FullName;
|
|
|
|
|
-
|
|
|
|
|
if (directoryCounter == 0)
|
|
if (directoryCounter == 0)
|
|
|
{
|
|
{
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ var currentDirectoryParent = new DirectoryInfo(currentDirectoryFullName).Parent;
|
|
|
|
|
+
|
|
|
|
|
+ Debug.Assert(currentDirectoryParent is not null, $"Should be {directoryCounter.ToString(CultureInfo.InvariantCulture)} levels deeper than {startDirectoryFullName}.");
|
|
|
|
|
+
|
|
|
|
|
+ currentDirectoryFullName = currentDirectoryParent.FullName;
|
|
|
|
|
+
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -795,7 +837,7 @@ namespace Renci.SshNet
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
// Don't create directory for first level
|
|
// Don't create directory for first level
|
|
|
- newDirectoryInfo = fileSystemInfo as DirectoryInfo;
|
|
|
|
|
|
|
+ newDirectoryInfo = (DirectoryInfo)fileSystemInfo;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
directoryCounter++;
|
|
directoryCounter++;
|