diff --git a/Renci.SshClient/Renci.SshNet/Common/PipeStream.cs b/Renci.SshClient/Renci.SshNet/Common/PipeStream.cs
index 670ab806..40e62cb4 100644
--- a/Renci.SshClient/Renci.SshNet/Common/PipeStream.cs
+++ b/Renci.SshClient/Renci.SshNet/Common/PipeStream.cs
@@ -127,7 +127,7 @@
///Methods were called after the stream was closed. 1
public override long Seek(long offset, SeekOrigin origin)
{
- throw new NotImplementedException();
+ throw new NotSupportedException();
}
///
@@ -139,7 +139,7 @@
///Methods were called after the stream was closed. 2
public override void SetLength(long value)
{
- throw new NotImplementedException();
+ throw new NotSupportedException();
}
///
@@ -160,9 +160,9 @@
public override int Read(byte[] buffer, int offset, int count)
{
if (offset != 0)
- throw new NotImplementedException("Offsets with value of non-zero are not supported");
+ throw new NotSupportedException("Offsets with value of non-zero are not supported");
if (buffer == null)
- throw new ArgumentException("Buffer is null");
+ throw new ArgumentNullException("Buffer is null");
if (offset + count > buffer.Length)
throw new ArgumentException("The sum of offset and count is greater than the buffer length. ");
if (offset < 0 || count < 0)
@@ -217,7 +217,7 @@
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer == null)
- throw new ArgumentException("Buffer is null");
+ throw new ArgumentNullException("Buffer is null");
if (offset + count > buffer.Length)
throw new ArgumentException("The sum of offset and count is greater than the buffer length. ");
if (offset < 0 || count < 0)
@@ -305,7 +305,7 @@
public override long Position
{
get { return 0; }
- set { throw new NotImplementedException(); }
+ set { throw new NotSupportedException(); }
}
#endregion
diff --git a/Renci.SshClient/Renci.SshNet/Common/SemaphoreLight.cs b/Renci.SshClient/Renci.SshNet/Common/SemaphoreLight.cs
index ee9eada4..1cbf4130 100644
--- a/Renci.SshClient/Renci.SshNet/Common/SemaphoreLight.cs
+++ b/Renci.SshClient/Renci.SshNet/Common/SemaphoreLight.cs
@@ -20,6 +20,7 @@ namespace Renci.SshNet.Common
/// the initial number of requests that can be granted concurrently.
///
/// The initial number of requests for the semaphore that can be granted concurrently.
+ /// is a negative number.
public SemaphoreLight(int initialCount)
{
if (initialCount < 0 )
diff --git a/Renci.SshClient/Renci.SshNet/Common/SshData.cs b/Renci.SshClient/Renci.SshNet/Common/SshData.cs
index e5822416..99dde274 100644
--- a/Renci.SshClient/Renci.SshNet/Common/SshData.cs
+++ b/Renci.SshClient/Renci.SshNet/Common/SshData.cs
@@ -73,8 +73,12 @@ namespace Renci.SshNet.Common
/// Loads data from specified bytes.
///
/// Bytes array.
+ /// is null.
public void Load(byte[] value)
{
+ if (value == null)
+ throw new ArgumentNullException("value");
+
this.LoadBytes(value);
this.LoadData();
}
@@ -93,8 +97,14 @@ namespace Renci.SshNet.Common
/// Loads data bytes into internal buffer.
///
/// The bytes.
+ /// is null.
protected void LoadBytes(byte[] bytes)
{
+ // Note about why I check for null here, and in Load(byte[]) in this class.
+ // This method is called by several other classes, such as SshNet.Messages.Message, SshNet.Sftp.SftpMessage.
+ if (bytes == null)
+ throw new ArgumentNullException("bytes");
+
this.ResetReader();
this._loadedData = bytes;
this._data = new List(bytes);
@@ -111,7 +121,7 @@ namespace Renci.SshNet.Common
///
/// Reads all data left in internal buffer at current position.
///
- ///
+ /// An array of bytes containing the remaining data in the internal buffer.
protected byte[] ReadBytes()
{
var data = new byte[this._data.Count - this._readerIndex];
@@ -123,9 +133,16 @@ namespace Renci.SshNet.Common
/// Reads next specified number of bytes data type from internal buffer.
///
/// Number of bytes to read.
- ///
+ /// An array of bytes that was read from the internal buffer.
+ /// is greater than the internal buffer size.
protected byte[] ReadBytes(int length)
{
+ // Note that this also prevents allocating non-relevant lengths, such as if length is greater than _data.Count but less than int.MaxValue.
+ // For the nerds, the condition translates to: if (length > data.Count && length < int.MaxValue)
+ // Which probably would cause all sorts of exception, most notably OutOfMemoryException.
+ if (length > this._data.Count)
+ throw new ArgumentOutOfRangeException("length");
+
var result = new byte[length];
this._data.CopyTo(this._readerIndex, result, 0, length);
this._readerIndex += length;
@@ -200,7 +217,7 @@ namespace Renci.SshNet.Common
if (length > int.MaxValue)
{
- throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "String that longer that {0} are not supported.", int.MaxValue));
+ throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
}
return Renci.SshNet.Common.ASCIIEncoding.Current.GetString(this.ReadBytes(length));
@@ -216,7 +233,7 @@ namespace Renci.SshNet.Common
if (length > int.MaxValue)
{
- throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "String that longer that {0} are not supported.", int.MaxValue));
+ throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
}
return this.ReadBytes(length);
@@ -265,6 +282,7 @@ namespace Renci.SshNet.Common
/// Writes bytes array data into internal buffer.
///
/// Byte array data to write.
+ /// is null.
protected void Write(IEnumerable data)
{
this._data.AddRange(data);
diff --git a/Renci.SshClient/Renci.SshNet/SftpClient.cs b/Renci.SshClient/Renci.SshNet/SftpClient.cs
index 0e5bed72..2defc59a 100644
--- a/Renci.SshClient/Renci.SshNet/SftpClient.cs
+++ b/Renci.SshClient/Renci.SshNet/SftpClient.cs
@@ -656,6 +656,7 @@ namespace Renci.SshNet
///
/// The path and name of the file to create.
/// A that provides read/write access to the file specified in path
+ /// is null.
public SftpFileStream Create(string path)
{
return new SftpFileStream(this._sftpSession, path, FileMode.Create, FileAccess.ReadWrite);
@@ -667,6 +668,7 @@ namespace Renci.SshNet
/// The path and name of the file to create.
/// The number of bytes buffered for reads and writes to the file.
/// A that provides read/write access to the file specified in path
+ /// is null.
public SftpFileStream Create(string path, int bufferSize)
{
return new SftpFileStream(this._sftpSession, path, FileMode.Create, FileAccess.ReadWrite, bufferSize);
@@ -677,6 +679,7 @@ namespace Renci.SshNet
///
/// The file to be opened for writing.
/// A that writes to the specified file using UTF-8 encoding.
+ /// is null.
public StreamWriter CreateText(string path)
{
return new StreamWriter(this.OpenWrite(path), Encoding.UTF8);
@@ -688,6 +691,7 @@ namespace Renci.SshNet
/// The file to be opened for writing.
/// The character encoding to use.
/// A that writes to the specified file using UTF-8 encoding.
+ /// is null.
public StreamWriter CreateText(string path, Encoding encoding)
{
return new StreamWriter(this.OpenWrite(path), encoding);
@@ -697,6 +701,7 @@ namespace Renci.SshNet
/// Deletes the specified file or directory. An exception is not thrown if the specified file does not exist.
///
/// The name of the file or directory to be deleted. Wildcard characters are not supported.
+ /// is null.
public void Delete(string path)
{
var file = this.Get(path);
@@ -709,6 +714,7 @@ namespace Renci.SshNet
///
/// The file or directory for which to obtain access date and time information.
/// A structure set to the date and time that the specified file or directory was last accessed. This value is expressed in local time.
+ /// is null.
public DateTime GetLastAccessTime(string path)
{
var file = this.Get(path);
@@ -721,6 +727,7 @@ namespace Renci.SshNet
///
/// The file or directory for which to obtain access date and time information.
/// A structure set to the date and time that the specified file or directory was last accessed. This value is expressed in UTC time.
+ /// is null.
public DateTime GetLastAccessTimeUtc(string path)
{
var file = this.Get(path);
@@ -733,6 +740,7 @@ namespace Renci.SshNet
///
/// The file or directory for which to obtain write date and time information.
/// A structure set to the date and time that the specified file or directory was last written to. This value is expressed in local time.
+ /// is null.
public DateTime GetLastWriteTime(string path)
{
var file = this.Get(path);
@@ -745,6 +753,7 @@ namespace Renci.SshNet
///
/// The file or directory for which to obtain write date and time information.
/// A structure set to the date and time that the specified file or directory was last written to. This value is expressed in UTC time.
+ /// is null.
public DateTime GetLastWriteTimeUtc(string path)
{
var file = this.Get(path);
@@ -758,6 +767,7 @@ namespace Renci.SshNet
/// The file to open.
/// A value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten.
/// An unshared that provides access to the specified file, with the specified mode and access.
+ /// is null.
public SftpFileStream Open(string path, FileMode mode)
{
return new SftpFileStream(this._sftpSession, path, mode, FileAccess.ReadWrite);
@@ -770,6 +780,7 @@ namespace Renci.SshNet
/// A value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten.
/// A value that specifies the operations that can be performed on the file.
/// An unshared that provides access to the specified file, with the specified mode and access.
+ /// is null.
public SftpFileStream Open(string path, FileMode mode, FileAccess access)
{
return new SftpFileStream(this._sftpSession, path, mode, access);
@@ -780,6 +791,7 @@ namespace Renci.SshNet
///
/// The file to be opened for reading.
/// A read-only System.IO.FileStream on the specified path.
+ /// is null.
public SftpFileStream OpenRead(string path)
{
return new SftpFileStream(this._sftpSession, path, FileMode.Open, FileAccess.Read);
@@ -790,6 +802,7 @@ namespace Renci.SshNet
///
/// The file to be opened for reading.
/// A on the specified path.
+ /// is null.
public StreamReader OpenText(string path)
{
return new StreamReader(this.OpenRead(path), Encoding.UTF8);
@@ -800,6 +813,7 @@ namespace Renci.SshNet
///
/// The file to be opened for writing.
/// An unshared object on the specified path with access.
+ /// is null.
public SftpFileStream OpenWrite(string path)
{
return new SftpFileStream(this._sftpSession, path, FileMode.OpenOrCreate, FileAccess.Write);
@@ -810,6 +824,7 @@ namespace Renci.SshNet
///
/// The file to open for reading.
/// A byte array containing the contents of the file.
+ /// is null.
public byte[] ReadAllBytes(string path)
{
using (var stream = this.OpenRead(path))
@@ -825,6 +840,7 @@ namespace Renci.SshNet
///
/// The file to open for reading.
/// A string array containing all lines of the file.
+ /// is null.
public string[] ReadAllLines(string path)
{
return this.ReadAllLines(path, Encoding.UTF8);
@@ -836,6 +852,7 @@ namespace Renci.SshNet
/// The file to open for reading.
/// The encoding applied to the contents of the file.
/// A string array containing all lines of the file.
+ /// is null.
public string[] ReadAllLines(string path, Encoding encoding)
{
var lines = new List();
@@ -854,6 +871,7 @@ namespace Renci.SshNet
///
/// The file to open for reading.
/// A string containing all lines of the file.
+ /// is null.
public string ReadAllText(string path)
{
return this.ReadAllText(path, Encoding.UTF8);
@@ -865,6 +883,7 @@ namespace Renci.SshNet
/// The file to open for reading.
/// The encoding applied to the contents of the file.
/// A string containing all lines of the file.
+ /// is null.
public string ReadAllText(string path, Encoding encoding)
{
var lines = new List();
@@ -879,6 +898,7 @@ namespace Renci.SshNet
///
/// The file to read.
/// The lines of the file.
+ /// is null.
public IEnumerable ReadLines(string path)
{
return this.ReadAllLines(path);
@@ -890,6 +910,7 @@ namespace Renci.SshNet
/// The file to read.
/// The encoding that is applied to the contents of the file.
/// The lines of the file.
+ /// is null.
public IEnumerable ReadLines(string path, Encoding encoding)
{
return this.ReadAllLines(path, encoding);
@@ -944,6 +965,7 @@ namespace Renci.SshNet
///
/// The file to write to.
/// The bytes to write to the file.
+ /// is null.
public void WriteAllBytes(string path, byte[] bytes)
{
using (var stream = this.OpenWrite(path))
@@ -957,6 +979,7 @@ namespace Renci.SshNet
///
/// The file to write to.
/// The lines to write to the file.
+ /// is null.
public void WriteAllLines(string path, IEnumerable contents)
{
this.WriteAllLines(path, contents, Encoding.UTF8);
@@ -967,6 +990,7 @@ namespace Renci.SshNet
///
/// The file to write to.
/// The string array to write to the file.
+ /// is null.
public void WriteAllLines(string path, string[] contents)
{
this.WriteAllLines(path, contents, Encoding.UTF8);
@@ -978,6 +1002,7 @@ namespace Renci.SshNet
/// The file to write to.
/// The lines to write to the file.
/// The character encoding to use.
+ /// is null.
public void WriteAllLines(string path, IEnumerable contents, Encoding encoding)
{
using (var stream = this.CreateText(path, encoding))
@@ -995,6 +1020,7 @@ namespace Renci.SshNet
/// The file to write to.
/// The string array to write to the file.
/// An object that represents the character encoding applied to the string array.
+ /// is null.
public void WriteAllLines(string path, string[] contents, Encoding encoding)
{
using (var stream = this.CreateText(path, encoding))
@@ -1011,6 +1037,7 @@ namespace Renci.SshNet
///
/// The file to write to.
/// The string to write to the file.
+ /// is null.
public void WriteAllText(string path, string contents)
{
using (var stream = this.CreateText(path))
@@ -1025,6 +1052,7 @@ namespace Renci.SshNet
/// The file to write to.
/// The string to write to the file.
/// The encoding to apply to the string.
+ /// is null.
public void WriteAllText(string path, string contents, Encoding encoding)
{
using (var stream = this.CreateText(path, encoding))
@@ -1038,6 +1066,7 @@ namespace Renci.SshNet
///
/// The path to the file.
/// The of the file on the path.
+ /// is null.
public SftpFileAttributes GetAttributes(string path)
{
var fullPath = this._sftpSession.GetCanonicalPath(path);
@@ -1050,6 +1079,7 @@ namespace Renci.SshNet
///
/// The path to the file.
/// The desired .
+ /// is null.
public void SetAttributes(string path, SftpFileAttributes fileAttributes)
{
var fullPath = this._sftpSession.GetCanonicalPath(path);
@@ -1057,6 +1087,7 @@ namespace Renci.SshNet
this._sftpSession.RequestSetStat(fullPath, fileAttributes);
}
+ // Please don't forget this when you implement these methods: is null.
//public FileSecurity GetAccessControl(string path);
//public FileSecurity GetAccessControl(string path, AccessControlSections includeSections);
//public DateTime GetCreationTime(string path);
diff --git a/Renci.SshClient/Renci.SshNet/SubsystemSession.cs b/Renci.SshClient/Renci.SshNet/SubsystemSession.cs
index e2fa5c6e..e4691fce 100644
--- a/Renci.SshClient/Renci.SshNet/SubsystemSession.cs
+++ b/Renci.SshClient/Renci.SshNet/SubsystemSession.cs
@@ -51,9 +51,19 @@ namespace Renci.SshNet.Sftp
//internal event EventHandler> AttributesMessageReceived;
#endregion
-
+
+ ///
+ /// Initializes a new instance of the SubsystemSession class.
+ ///
+ /// or is null.
public SubsystemSession(Session session, string subsystemName, TimeSpan operationTimeout)
{
+ if (session == null)
+ throw new ArgumentNullException("session");
+
+ if (subsystemName == null)
+ throw new ArgumentNullException("subsystemName");
+
this._session = session;
this._subsystemName = subsystemName;
this._operationTimeout = operationTimeout;