From d8ee7d17d2dd8070ebd0cd98576cb4490ff840f9 Mon Sep 17 00:00:00 2001 From: Kenneth_aa_cp Date: Wed, 24 Aug 2011 03:00:58 +0000 Subject: [PATCH] SshData.cs - Added 4 exception documentation, added 3 parameter checks, fixed typo in exception message for ReadString/ReadBinaryString. Also note that any call to SshData.Write(IEnumerable) will throw if passed null, List.AddRange does that for us. SubsystemSession.cs - Added 1 exception documentation and parameter check on Constructor(Session,string,TimeSpan). SftpClient.cs - Added more exception documentation than I care to count. PipeStream.cs - Fixed mismatch between documentation and the actual exception in Write(byte[], int, int). Also in property Position, throwing NotImplemented but documented NotSupported. Also happens elsewhere o.O - I'm not touching this code anymore, see Workitem 819. SemaphoreLight.cs - Added 1 exception documentation. --- .../Renci.SshNet/Common/PipeStream.cs | 12 +++---- .../Renci.SshNet/Common/SemaphoreLight.cs | 1 + .../Renci.SshNet/Common/SshData.cs | 26 +++++++++++++--- Renci.SshClient/Renci.SshNet/SftpClient.cs | 31 +++++++++++++++++++ .../Renci.SshNet/SubsystemSession.cs | 12 ++++++- 5 files changed, 71 insertions(+), 11 deletions(-) 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;