소스 검색

Fix international support, now all differnt character sets should work, depends on windows default selection
Add international support test case
Add XML documention to some members of SubsystemSession class

olegkap_cp 14 년 전
부모
커밋
ef33d78e89
34개의 변경된 파일329개의 추가작업 그리고 94개의 파일을 삭제
  1. 4 1
      Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj
  2. 4 1
      Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj
  3. 19 0
      Renci.SshClient/Renci.SshNet.Tests/SftpClientTests/GetTest.cs
  4. 4 1
      Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj
  5. 174 0
      Renci.SshClient/Renci.SshNet/Common/ASCIIEncoding.cs
  6. 39 11
      Renci.SshClient/Renci.SshNet/Common/SshData.cs
  7. 1 1
      Renci.SshClient/Renci.SshNet/Messages/Authentication/BannerMessage.cs
  8. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
  9. 4 4
      Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessage.cs
  10. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs
  11. 1 1
      Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs
  12. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs
  13. 1 1
      Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
  14. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs
  15. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs
  16. 1 1
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs
  17. 3 3
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs
  18. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs
  19. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs
  20. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs
  21. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs
  22. 3 3
      Renci.SshClient/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs
  23. 1 1
      Renci.SshClient/Renci.SshNet/Messages/Transport/DisconnectMessage.cs
  24. 1 1
      Renci.SshClient/Renci.SshNet/Messages/Transport/ServiceAcceptMessage.cs
  25. 2 2
      Renci.SshClient/Renci.SshNet/Messages/Transport/ServiceRequestMessage.cs
  26. 3 3
      Renci.SshClient/Renci.SshNet/PrivateKeyConnectionInfo.cs
  27. 1 17
      Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
  28. 1 1
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs
  29. 1 0
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs
  30. 1 1
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs
  31. 1 1
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs
  32. 1 1
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRmDirRequest.cs
  33. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs
  34. 38 18
      Renci.SshClient/Renci.SshNet/SubsystemSession.cs

+ 4 - 1
Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj

@@ -70,6 +70,9 @@
     <Compile Include="..\Renci.SshNet\CipherInfo.cs">
       <Link>CipherInfo.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Common\ASCIIEncoding.cs">
+      <Link>Common\ASCIIEncoding.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Common\AsyncResult.cs">
       <Link>Common\AsyncResult.cs</Link>
     </Compile>
@@ -709,7 +712,7 @@
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
     <VisualStudio>
-      <UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
+      <UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
     </VisualStudio>
   </ProjectExtensions>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 4 - 1
Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj

@@ -84,6 +84,9 @@
     <Compile Include="..\Renci.SshNet\CipherInfo.cs">
       <Link>CipherInfo.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Common\ASCIIEncoding.cs">
+      <Link>Common\ASCIIEncoding.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Common\AsyncResult.cs">
       <Link>Common\AsyncResult.cs</Link>
     </Compile>
@@ -688,7 +691,7 @@
       <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
         <SilverlightProjectProperties />
       </FlavorProperties>
-      <UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
+      <UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
     </VisualStudio>
   </ProjectExtensions>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 19 - 0
Renci.SshClient/Renci.SshNet.Tests/SftpClientTests/GetTest.cs

@@ -84,5 +84,24 @@ namespace Renci.SshNet.Tests.SftpClientTests
 				sftp.Disconnect();
 			}
 		}
+
+        [TestMethod]
+        [TestCategory("Sftp")]
+        public void Test_Get_International_File()
+        {
+            using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+            {
+                sftp.Connect();
+
+                sftp.UploadFile(new MemoryStream(), "test-üöä-");
+
+                var file = sftp.Get("test-üöä-");
+
+                Assert.AreEqual("/home/tester/test-üöä-", file.FullName);
+                Assert.IsTrue(file.IsRegularFile);
+                Assert.IsFalse(file.IsDirectory);
+            }
+        }
+
     }
 }

+ 4 - 1
Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj

@@ -77,6 +77,9 @@
     <Compile Include="..\Renci.SshNet\CipherInfo.cs">
       <Link>CipherInfo.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Common\ASCIIEncoding.cs">
+      <Link>Common\ASCIIEncoding.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Common\AsyncResult.cs">
       <Link>Common\AsyncResult.cs</Link>
     </Compile>
@@ -690,7 +693,7 @@
   <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
   <ProjectExtensions>
     <VisualStudio>
-      <UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
+      <UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
     </VisualStudio>
   </ProjectExtensions>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 174 - 0
Renci.SshClient/Renci.SshNet/Common/ASCIIEncoding.cs

@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class ASCIIEncoding : Encoding
+    {
+        private readonly char _fallbackChar;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ASCIIEncoding"/> class.
+        /// </summary>
+        public ASCIIEncoding()
+        {
+            this._fallbackChar = '?';
+        }
+
+        /// <summary>
+        /// Calculates the number of bytes produced by encoding a set of characters from the specified character array.
+        /// </summary>
+        /// <param name="chars">The character array containing the set of characters to encode.</param>
+        /// <param name="index">The index of the first character to encode.</param>
+        /// <param name="count">The number of characters to encode.</param>
+        /// <returns>
+        /// The number of bytes produced by encoding the specified characters.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="chars"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="index"/> or <paramref name="count"/> is less than zero.-or- <paramref name="index"/> and <paramref name="count"/> do not denote a valid range in <paramref name="chars"/>. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetByteCount(char[] chars, int index, int count)
+        {
+            return count;
+        }
+
+        /// <summary>
+        /// Encodes a set of characters from the specified character array into the specified byte array.
+        /// </summary>
+        /// <param name="chars">The character array containing the set of characters to encode.</param>
+        /// <param name="charIndex">The index of the first character to encode.</param>
+        /// <param name="charCount">The number of characters to encode.</param>
+        /// <param name="bytes">The byte array to contain the resulting sequence of bytes.</param>
+        /// <param name="byteIndex">The index at which to start writing the resulting sequence of bytes.</param>
+        /// <returns>
+        /// The actual number of bytes written into <paramref name="bytes"/>.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="chars"/> is null.-or- <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="charIndex"/> or <paramref name="charCount"/> or <paramref name="byteIndex"/> is less than zero.-or- <paramref name="charIndex"/> and <paramref name="charCount"/> do not denote a valid range in <paramref name="chars"/>.-or- <paramref name="byteIndex"/> is not a valid index in <paramref name="bytes"/>. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentException">
+        ///   <paramref name="bytes"/> does not have enough capacity from <paramref name="byteIndex"/> to the end of the array to accommodate the resulting bytes. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+        {
+            for (int i = 0; i < charCount; i++)
+            {
+                var b = (byte)chars[i + charIndex];
+
+                if (b > 127)
+                    b = (byte)this._fallbackChar;
+
+                bytes[i + byteIndex] = b;
+            }
+            return charCount;
+        }
+
+        /// <summary>
+        /// Calculates the number of characters produced by decoding a sequence of bytes from the specified byte array.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <param name="index">The index of the first byte to decode.</param>
+        /// <param name="count">The number of bytes to decode.</param>
+        /// <returns>
+        /// The number of characters produced by decoding the specified sequence of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="index"/> or <paramref name="count"/> is less than zero.-or- <paramref name="index"/> and <paramref name="count"/> do not denote a valid range in <paramref name="bytes"/>. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override int GetCharCount(byte[] bytes, int index, int count)
+        {
+            return count;
+        }
+
+        /// <summary>
+        /// Decodes a sequence of bytes from the specified byte array into the specified character array.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <param name="byteIndex">The index of the first byte to decode.</param>
+        /// <param name="byteCount">The number of bytes to decode.</param>
+        /// <param name="chars">The character array to contain the resulting set of characters.</param>
+        /// <param name="charIndex">The index at which to start writing the resulting set of characters.</param>
+        /// <returns>
+        /// The actual number of characters written into <paramref name="chars"/>.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null.-or- <paramref name="chars"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="byteIndex"/> or <paramref name="byteCount"/> or <paramref name="charIndex"/> is less than zero.-or- <paramref name="byteindex"/> and <paramref name="byteCount"/> do not denote a valid range in <paramref name="bytes"/>.-or- <paramref name="charIndex"/> is not a valid index in <paramref name="chars"/>. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentException">
+        ///   <paramref name="chars"/> does not have enough capacity from <paramref name="charIndex"/> to the end of the array to accommodate the resulting characters. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+        {
+            for (int i = 0; i < byteCount; i++)
+            {
+                var b = bytes[i + byteIndex];
+                char ch;
+
+                if (b > 127)
+                {
+                    ch = this._fallbackChar;
+                }
+                else 
+                {
+                    ch = (char)b;
+                }
+
+                chars[i + charIndex] = ch;
+            }
+            return byteCount;
+        }
+
+        /// <summary>
+        /// Calculates the maximum number of bytes produced by encoding the specified number of characters.
+        /// </summary>
+        /// <param name="charCount">The number of characters to encode.</param>
+        /// <returns>
+        /// The maximum number of bytes produced by encoding the specified number of characters.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="charCount"/> is less than zero. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetMaxByteCount(int charCount)
+        {
+            return charCount;
+        }
+
+        /// <summary>
+        /// Calculates the maximum number of characters produced by decoding the specified number of bytes.
+        /// </summary>
+        /// <param name="byteCount">The number of bytes to decode.</param>
+        /// <returns>
+        /// The maximum number of characters produced by decoding the specified number of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="byteCount"/> is less than zero. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override int GetMaxCharCount(int byteCount)
+        {
+            return byteCount;
+        }
+    }
+}

+ 39 - 11
Renci.SshClient/Renci.SshNet/Common/SshData.cs

@@ -11,6 +11,14 @@ namespace Renci.SshNet.Common
     /// </summary>
     public abstract class SshData
     {
+        private static Encoding _ascii = new ASCIIEncoding();
+
+#if SILVERLIGHT
+        private static Encoding _utf8 = Encoding.UTF8;
+#else
+        private static Encoding _utf8 = Encoding.Default;
+#endif
+
         /// <summary>
         /// Data byte array that hold message unencrypted data
         /// </summary>
@@ -207,6 +215,21 @@ namespace Renci.SshNet.Common
             return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
         }
 
+        /// <summary>
+        /// Reads next string data type from internal buffer.
+        /// </summary>
+        /// <returns>string read</returns>
+        protected string ReadAsciiString()
+        {
+            var length = this.ReadUInt32();
+
+            if (length > (uint)int.MaxValue)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
+            }
+            return _ascii.GetString(this.ReadBytes((int)length), 0, (int)length);
+        }
+
         /// <summary>
         /// Reads next string data type from internal buffer.
         /// </summary>
@@ -219,9 +242,10 @@ namespace Renci.SshNet.Common
             {
                 throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
             }
-            return Encoding.UTF8.GetString(this.ReadBytes((int)length), 0, (int)length);
+            return _utf8.GetString(this.ReadBytes((int)length), 0, (int)length);
         }
 
+
         /// <summary>
         /// Reads next string data type from internal buffer.
         /// </summary>
@@ -349,28 +373,32 @@ namespace Renci.SshNet.Common
         }
 
         /// <summary>
-        /// Writes string data into internal buffer.
+        /// Writes string data into internal buffer using default encoding.
         /// </summary>
         /// <param name="data">string data to write.</param>
-        /// <param name="encoding">String text encoding to use.</param>
         /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
-        protected void Write(string data, Encoding encoding)
+        protected void Write(string data)
         {
             if (data == null)
                 throw new ArgumentNullException("data");
 
-            var bytes = encoding.GetBytes(data);
+            var bytes = _utf8.GetBytes(data);
             this.Write((uint)bytes.Length);
             this.Write(bytes);
         }
 
         /// <summary>
-        /// Writes string data into internal buffer.
+        /// Writes string data into internal buffer as ASCII.
         /// </summary>
         /// <param name="data">string data to write.</param>
-        protected void Write(string data)
+        protected void WriteAscii(string data)
         {
-            this.Write(data, Encoding.UTF8);
+            if (data == null)
+                throw new ArgumentNullException("data");
+
+            var bytes = _ascii.GetBytes(data);
+            this.Write((uint)bytes.Length);
+            this.Write(bytes);
         }
 
         /// <summary>
@@ -404,7 +432,7 @@ namespace Renci.SshNet.Common
         /// <param name="data">name-list data to write.</param>
         protected void Write(string[] data)
         {
-            this.Write(string.Join(",", data));
+            this.WriteAscii(string.Join(",", data));
         }
 
         /// <summary>
@@ -415,8 +443,8 @@ namespace Renci.SshNet.Common
         {
             foreach (var item in data)
             {
-                this.Write(item.Key);
-                this.Write(item.Value);
+                this.WriteAscii(item.Key);
+                this.WriteAscii(item.Value);
             }
         }
     }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Authentication/BannerMessage.cs

@@ -32,7 +32,7 @@ namespace Renci.SshNet.Messages.Authentication
         /// </summary>
         protected override void SaveData()
         {
-            this.Write(this.Message, Encoding.UTF8);
+            this.Write(this.Message);
             this.Write(this.Language);
         }
     }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs

@@ -27,7 +27,7 @@ namespace Renci.SshNet.Messages.Authentication
         /// </summary>
         protected override void LoadData()
         {
-            this.PublicKeyAlgorithmName = this.ReadString();
+            this.PublicKeyAlgorithmName = this.ReadAsciiString();
             this.PublicKeyData = this.ReadBinaryString();
         }
 
@@ -36,7 +36,7 @@ namespace Renci.SshNet.Messages.Authentication
         /// </summary>
         protected override void SaveData()
         {
-            this.Write(this.PublicKeyAlgorithmName);
+            this.WriteAscii(this.PublicKeyAlgorithmName);
             this.WriteBinaryString(this.PublicKeyData);
         }
     }

+ 4 - 4
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessage.cs

@@ -54,19 +54,19 @@ namespace Renci.SshNet.Messages.Authentication
         /// </summary>
         protected override void SaveData()
         {
-            this.Write(this.Username, Encoding.UTF8);
+            this.Write(this.Username);
             switch (this.ServiceName)
             {
                 case ServiceName.UserAuthentication:
-                    this.Write("ssh-userauth", Encoding.UTF8);
+                    this.WriteAscii("ssh-userauth");
                     break;
                 case ServiceName.Connection:
-                    this.Write("ssh-connection", Encoding.UTF8);
+                    this.WriteAscii("ssh-connection");
                     break;
                 default:
                     throw new NotSupportedException("Not supported service name");
             }
-            this.Write(this.MethodName);
+            this.WriteAscii(this.MethodName);
         }
     }
 }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs

@@ -83,10 +83,10 @@ namespace Renci.SshNet.Messages.Authentication
         {
             base.SaveData();
 
-            this.Write(this.PublicKeyAlgorithm);
+            this.WriteAscii(this.PublicKeyAlgorithm);
             this.WriteBinaryString(this.PublicHostKey);
             this.Write(this.ClientHostName);
-            this.Write(this.ClientUsername, Encoding.UTF8);
+            this.Write(this.ClientUsername);
 
             if (this.Signature != null)
                 this.WriteBinaryString(this.Signature);

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs

@@ -52,7 +52,7 @@ namespace Renci.SshNet.Messages.Authentication
 
             this.Write(this.Language);
 
-            this.Write(this.SubMethods, Encoding.UTF8);
+            this.Write(this.SubMethods);
         }
     }
 }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs

@@ -65,11 +65,11 @@ namespace Renci.SshNet.Messages.Authentication
 
             this.Write(!string.IsNullOrEmpty(this.NewPassword));
 
-            this.Write(this.Password, Encoding.UTF8);
+            this.Write(this.Password);
 
             if (!string.IsNullOrEmpty(this.NewPassword))
             {
-                this.Write(this.NewPassword, Encoding.UTF8);
+                this.Write(this.NewPassword);
             }
         }
     }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs

@@ -85,7 +85,7 @@ namespace Renci.SshNet.Messages.Authentication
             {
                 this.Write(true);
             }
-            this.Write(this.PublicKeyAlgorithmName);
+            this.WriteAscii(this.PublicKeyAlgorithmName);
             this.WriteBinaryString(this.PublicKeyData);
             if (this.Signature != null)
                 this.WriteBinaryString(this.Signature);

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs

@@ -72,7 +72,7 @@ namespace Renci.SshNet.Messages.Connection
         /// </summary>
         protected override void LoadData()
         {
-            var channelName = this.ReadString();
+            var channelName = this.ReadAsciiString();
             this.LocalChannelNumber = this.ReadUInt32();
             this.InitialWindowSize = this.ReadUInt32();
             this.MaximumPacketSize = this.ReadUInt32();
@@ -108,7 +108,7 @@ namespace Renci.SshNet.Messages.Connection
         /// </summary>
         protected override void SaveData()
         {
-            this.Write(this.ChannelType);
+            this.WriteAscii(this.ChannelType);
             this.Write(this.LocalChannelNumber);
             this.Write(this.InitialWindowSize);
             this.Write(this.MaximumPacketSize);

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs

@@ -49,7 +49,7 @@ namespace Renci.SshNet.Messages.Connection
         {
             base.LoadData();
 
-            this.RequestName = this.ReadString();
+            this.RequestName = this.ReadAsciiString();
             this.RequestData = this.ReadBytes();
         }
 
@@ -60,7 +60,7 @@ namespace Renci.SshNet.Messages.Connection
         {
             base.SaveData();
 
-            this.Write(this.RequestName);
+            this.WriteAscii(this.RequestName);
             this.Write(this.RequestData);
         }
     }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs

@@ -63,7 +63,7 @@ namespace Renci.SshNet.Messages.Connection
         {
             base.SaveData();
 
-            this.Write(this.Command, Encoding.UTF8);
+            this.Write(this.Command);
         }
     }
 }

+ 3 - 3
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs

@@ -79,7 +79,7 @@ namespace Renci.SshNet.Messages.Connection
         {
             base.LoadData();
 
-            this.SignalName = this.ReadString();
+            this.SignalName = this.ReadAsciiString();
             this.CoreDumped = this.ReadBoolean();
             this.ErrorMessage = this.ReadString();
             this.Language = this.ReadString();
@@ -92,10 +92,10 @@ namespace Renci.SshNet.Messages.Connection
         {
             base.SaveData();
 
-            this.Write(this.SignalName);
+            this.WriteAscii(this.SignalName);
             this.Write(this.CoreDumped);
             this.Write(this.ErrorMessage);
-            this.Write(this.Language, Encoding.UTF8);
+            this.Write(this.Language);
         }
 
     }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs

@@ -109,7 +109,7 @@
             this.Rows = this.ReadUInt32();
             this.PixelWidth = this.ReadUInt32();
             this.PixelHeight = this.ReadUInt32();
-            this.TerminalMode = this.ReadString();
+            this.TerminalMode = this.ReadAsciiString();
         }
 
         /// <summary>
@@ -124,7 +124,7 @@
             this.Write(this.Rows);
             this.Write(this.Rows);
             this.Write(this.PixelHeight);
-            this.Write(this.TerminalMode);
+            this.WriteAscii(this.TerminalMode);
 
         }
     }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs

@@ -54,7 +54,7 @@
         {
             base.LoadData();
 
-            this.SignalName = this.ReadString();
+            this.SignalName = this.ReadAsciiString();
         }
 
         /// <summary>
@@ -64,7 +64,7 @@
         {
             base.SaveData();
 
-            this.Write(this.SignalName);
+            this.WriteAscii(this.SignalName);
         }
     }
 }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs

@@ -54,7 +54,7 @@
         {
             base.LoadData();
 
-            this.SubsystemName = this.ReadString();
+            this.SubsystemName = this.ReadAsciiString();
         }
 
         /// <summary>
@@ -64,7 +64,7 @@
         {
             base.SaveData();
 
-            this.Write(this.SubsystemName);
+            this.WriteAscii(this.SubsystemName);
         }
     }
 }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs

@@ -85,7 +85,7 @@
             base.LoadData();
 
             this.IsSingleConnection = this.ReadBoolean();
-            this.AuthenticationProtocol = this.ReadString();
+            this.AuthenticationProtocol = this.ReadAsciiString();
             this.AuthenticationCookie = this.ReadBinaryString();
             this.ScreenNumber = this.ReadUInt32();
         }
@@ -98,7 +98,7 @@
             base.SaveData();
 
             this.Write(this.IsSingleConnection);
-            this.Write(this.AuthenticationProtocol);
+            this.WriteAscii(this.AuthenticationProtocol);
             this.WriteBinaryString(this.AuthenticationCookie);
             this.Write(this.ScreenNumber);
         }

+ 3 - 3
Renci.SshClient/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs

@@ -73,7 +73,7 @@ namespace Renci.SshNet.Messages.Connection
         /// </summary>
         protected override void LoadData()
         {
-            var requestName = this.ReadString();
+            var requestName = this.ReadAsciiString();
             switch (requestName)
             {
                 case "tcpip-forward":
@@ -99,10 +99,10 @@ namespace Renci.SshNet.Messages.Connection
             switch (this.RequestName)
             {
                 case GlobalRequestName.TcpIpForward:
-                    this.Write("tcpip-forward");
+                    this.WriteAscii("tcpip-forward");
                     break;
                 case GlobalRequestName.CancelTcpIpForward:
-                    this.Write("cancel-tcpip-forward");
+                    this.WriteAscii("cancel-tcpip-forward");
                     break;
                 default:
                     break;

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Transport/DisconnectMessage.cs

@@ -58,7 +58,7 @@ namespace Renci.SshNet.Messages.Transport
         protected override void SaveData()
         {
             this.Write((uint)this.ReasonCode);
-            this.Write(this.Description, Encoding.UTF8);
+            this.Write(this.Description);
             this.Write(this.Language ?? "en");
         }
     }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Transport/ServiceAcceptMessage.cs

@@ -21,7 +21,7 @@ namespace Renci.SshNet.Messages.Transport
         /// </summary>
         protected override void LoadData()
         {
-            var serviceName = this.ReadString();
+            var serviceName = this.ReadAsciiString();
             switch (serviceName)
             {
                 case "ssh-userauth":

+ 2 - 2
Renci.SshClient/Renci.SshNet/Messages/Transport/ServiceRequestMessage.cs

@@ -41,10 +41,10 @@ namespace Renci.SshNet.Messages.Transport
             switch (this.ServiceName)
             {
                 case ServiceName.UserAuthentication:
-                    this.Write("ssh-userauth");
+                    this.WriteAscii("ssh-userauth");
                     break;
                 case ServiceName.Connection:
-                    this.Write("ssh-connection");
+                    this.WriteAscii("ssh-connection");
                     break;
                 default:
                     throw new NotSupportedException("Not supported service name");

+ 3 - 3
Renci.SshClient/Renci.SshNet/PrivateKeyConnectionInfo.cs

@@ -177,10 +177,10 @@ namespace Renci.SshNet
                 this.WriteBinaryString(this._sessionId);
                 this.Write((byte)50);
                 this.Write(this._message.Username);
-                this.Write("ssh-connection");
-                this.Write("publickey");
+                this.WriteAscii("ssh-connection");
+                this.WriteAscii("publickey");
                 this.Write((byte)1);
-                this.Write(this._message.PublicKeyAlgorithmName);
+                this.WriteAscii(this._message.PublicKeyAlgorithmName);
                 this.WriteBinaryString(this._message.PublicKeyData);
             }
         }

+ 1 - 17
Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj

@@ -36,23 +36,6 @@
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Release\Renci.SshNet.xml</DocumentationFile>
   </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugNoTimeout|AnyCPU'">
-    <DebugSymbols>true</DebugSymbols>
-    <OutputPath>bin\DebugNoTimeout\</OutputPath>
-    <DefineConstants>TRACE;DEBUG;NOTIMEOUT</DefineConstants>
-    <DebugType>full</DebugType>
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <CodeAnalysisLogFile>bin\Debug\Renci.SshClient.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
-    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
-    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
-    <ErrorReport>prompt</ErrorReport>
-    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
-    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
-    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
-    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
-    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
-    <DocumentationFile>bin\DebugNoTimeout\Renci.SshNet.xml</DocumentationFile>
-  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -72,6 +55,7 @@
     <Compile Include="Channels\ChannelSession.cs" />
     <Compile Include="Channels\ChannelTypes.cs" />
     <Compile Include="CipherInfo.cs" />
+    <Compile Include="Common\ASCIIEncoding.cs" />
     <Compile Include="Common\AsyncResult.cs" />
     <Compile Include="Common\AuthenticationBannerEventArgs.cs" />
     <Compile Include="Common\AuthenticationEventArgs.cs" />

+ 1 - 1
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs

@@ -31,7 +31,7 @@ namespace Renci.SshNet.Sftp.Requests
         protected override void SaveData()
         {
             base.SaveData();
-            this.Write(this.Path, Encoding.UTF8);
+            this.Write(this.Path);
         }
     }
 }

+ 1 - 0
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs

@@ -43,6 +43,7 @@ namespace Renci.SshNet.Sftp.Requests
         protected override void SaveData()
         {
             base.SaveData();
+
             this.Write(this.Filename);
             this.Write((uint)this.Flags);
             this.Write(this.Attributes);

+ 1 - 1
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs

@@ -31,7 +31,7 @@ namespace Renci.SshNet.Sftp.Requests
         protected override void SaveData()
         {
             base.SaveData();
-            this.Write(this.Path, Encoding.UTF8);
+            this.Write(this.Path);
         }
     }
 }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs

@@ -30,7 +30,7 @@ namespace Renci.SshNet.Sftp.Requests
         protected override void SaveData()
         {
             base.SaveData();
-            this.Write(this.Filename, Encoding.UTF8);
+            this.Write(this.Filename);
         }
     }
 }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRmDirRequest.cs

@@ -30,7 +30,7 @@ namespace Renci.SshNet.Sftp.Requests
         protected override void SaveData()
         {
             base.SaveData();
-            this.Write(this.Path, Encoding.UTF8);
+            this.Write(this.Path);
         }
     }
 }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs

@@ -34,8 +34,8 @@ namespace Renci.SshNet.Sftp.Requests
         protected override void SaveData()
         {
             base.SaveData();
-            this.Write(this.NewLinkPath, Encoding.UTF8);
-            this.Write(this.ExistingPath, Encoding.UTF8);
+            this.Write(this.NewLinkPath);
+            this.Write(this.ExistingPath);
         }
     }
 }

+ 38 - 18
Renci.SshClient/Renci.SshNet/SubsystemSession.cs

@@ -14,6 +14,9 @@ using Renci.SshNet.Messages.Connection;
 
 namespace Renci.SshNet.Sftp
 {
+    /// <summary>
+    /// Base class for SSH subsystem implementations
+    /// </summary>
     public abstract class SubsystemSession : IDisposable
     {
         private Session _session;
@@ -26,10 +29,19 @@ namespace Renci.SshNet.Sftp
 
         private EventWaitHandle _errorOccuredWaitHandle = new AutoResetEvent(false);
 
+        /// <summary>
+        /// Specifies a timeout to wait for operation to complete
+        /// </summary>
         protected TimeSpan _operationTimeout;
 
-        public event EventHandler<ExceptionEventArgs> ErrorOccured;
+        /// <summary>
+        /// Occurs when an error occurred.
+        /// </summary>
+        public event EventHandler<ExceptionEventArgs> ErrorOccurred;
 
+        /// <summary>
+        /// Gets the channel number.
+        /// </summary>
         protected uint ChannelNumber
         {
             get
@@ -37,21 +49,7 @@ namespace Renci.SshNet.Sftp
                 return this._channel.RemoteChannelNumber;
             }
         }
-
-        #region SFTP messages
-
-        //internal event EventHandler<MessageEventArgs<StatusMessage>> StatusMessageReceived;
-
-        //internal event EventHandler<MessageEventArgs<DataMessage>> DataMessageReceived;
-
-        //internal event EventHandler<MessageEventArgs<HandleMessage>> HandleMessageReceived;
-
-        //internal event EventHandler<MessageEventArgs<NameMessage>> NameMessageReceived;
-
-        //internal event EventHandler<MessageEventArgs<AttributesMessage>> AttributesMessageReceived;
-
-        #endregion
-        
+       
         /// <summary>
         /// Initializes a new instance of the SubsystemSession class.
         /// </summary>
@@ -69,6 +67,9 @@ namespace Renci.SshNet.Sftp
             this._operationTimeout = operationTimeout;
         }
 
+        /// <summary>
+        /// Connects subsystem on SSH channel.
+        /// </summary>
         public void Connect()
         {
             this._channel = this._session.CreateChannel<ChannelSession>();
@@ -84,29 +85,48 @@ namespace Renci.SshNet.Sftp
             this.OnChannelOpen();
         }
 
+        /// <summary>
+        /// Disconnects subsystem channel.
+        /// </summary>
         public void Disconnect()
         {
             this._channel.Close();
         }
 
+        /// <summary>
+        /// Sends data to the subsystem.
+        /// </summary>
+        /// <param name="message">The message.</param>
         public void SendData(ChannelDataMessage message)
         {
             this._session.SendMessage(message);
         }
 
+        /// <summary>
+        /// Called when channel is open.
+        /// </summary>
         protected abstract void OnChannelOpen();
 
+        /// <summary>
+        /// Called when data is received.
+        /// </summary>
+        /// <param name="dataTypeCode">The data type code.</param>
+        /// <param name="data">The data.</param>
         protected abstract void OnDataReceived(uint dataTypeCode, byte[] data);
 
+        /// <summary>
+        /// Raises the error.
+        /// </summary>
+        /// <param name="error">The error.</param>
         protected void RaiseError(Exception error)
         {
             this._exception = error;
 
             this._errorOccuredWaitHandle.Set();
 
-            if (this.ErrorOccured != null)
+            if (this.ErrorOccurred != null)
             {
-                this.ErrorOccured(this, new ExceptionEventArgs(error));
+                this.ErrorOccurred(this, new ExceptionEventArgs(error));
             }
         }