瀏覽代碼

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));
             }
         }