浏览代码

Refactor SFTP to prepare for multiple SFTP version support and add suport for versions 0 thru 3

olegkap_cp 13 年之前
父节点
当前提交
44b447afc4
共有 32 个文件被更改,包括 162 次插入91 次删除
  1. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/PosixRenameRequest.cs
  2. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs
  3. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs
  4. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs
  5. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs
  6. 4 4
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs
  7. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs
  8. 4 4
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs
  9. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs
  10. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs
  11. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs
  12. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs
  13. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs
  14. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs
  15. 4 1
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRequest.cs
  16. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRmDirRequest.cs
  17. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpSetStatRequest.cs
  18. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpStatRequest.cs
  19. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs
  20. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpWriteRequest.cs
  21. 2 2
      Renci.SshClient/Renci.SshNet/Sftp/Requests/StatVfsRequest.cs
  22. 5 0
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpAttrsResponse.cs
  23. 5 0
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpDataResponse.cs
  24. 5 0
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpExtendedReplyResponse.cs
  25. 5 0
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpHandleResponse.cs
  26. 3 2
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpNameResponse.cs
  27. 7 0
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpResponse.cs
  28. 11 2
      Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpStatusResponse.cs
  29. 5 0
      Renci.SshClient/Renci.SshNet/Sftp/Responses/StatVfsResponse.cs
  30. 9 9
      Renci.SshClient/Renci.SshNet/Sftp/SftpMessage.cs
  31. 58 32
      Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
  32. 1 1
      Renci.SshClient/Renci.SshNet/SftpClient.cs

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

@@ -16,8 +16,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string NewPath { get; private set; }
 
-        public PosixRenameRequest(uint requestId, string oldPath, string newPath, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public PosixRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.OldPath = oldPath;
             this.NewPath = newPath;

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public byte[] Handle { get; private set; }
 
-        public SftpCloseRequest(uint requestId, byte[] handle, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpCloseRequest(uint protocolVersion, uint requestId, byte[] handle, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Handle = handle;
         }

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

@@ -17,8 +17,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public SftpFileAttributes Attributes { get; private set; }
 
-        public SftpFSetStatRequest(uint requestId, byte[] handle, SftpFileAttributes attributes, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpFSetStatRequest(uint protocolVersion, uint requestId, byte[] handle, SftpFileAttributes attributes, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Handle = handle;
             this.Attributes = attributes;

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public byte[] Handle { get; private set; }
 
-        public SftpFStatRequest(uint requestId, byte[] handle, Action<SftpAttrsResponse> attrsAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpFStatRequest(uint protocolVersion, uint requestId, byte[] handle, Action<SftpAttrsResponse> attrsAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Handle = handle;
             this.SetAction(attrsAction);

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public SftpLStatRequest(uint requestId, string path, Action<SftpAttrsResponse> attrsAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpLStatRequest(uint protocolVersion, uint requestId, string path, Action<SftpAttrsResponse> attrsAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.SetAction(attrsAction);

+ 4 - 4
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs

@@ -17,15 +17,15 @@ namespace Renci.SshNet.Sftp.Requests
 
         public SftpFileAttributes Attributes { get; private set; }
 
-        public SftpMkDirRequest(uint requestId, string path, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpMkDirRequest(uint protocolVersion, uint requestId, string path, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.Attributes = new SftpFileAttributes();
         }
 
-        public SftpMkDirRequest(uint requestId, string path, SftpFileAttributes attributes, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpMkDirRequest(uint protocolVersion, uint requestId, string path, SftpFileAttributes attributes, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.Attributes = attributes;

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public SftpOpenDirRequest(uint requestId, string path, Action<SftpHandleResponse> handleAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpOpenDirRequest(uint protocolVersion, uint requestId, string path, Action<SftpHandleResponse> handleAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.SetAction(handleAction);

+ 4 - 4
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs

@@ -19,13 +19,13 @@ namespace Renci.SshNet.Sftp.Requests
 
         public SftpFileAttributes Attributes { get; private set; }
 
-        public SftpOpenRequest(uint requestId, string fileName, Flags flags, Action<SftpHandleResponse> handleAction, Action<SftpStatusResponse> statusAction)
-            : this(requestId, fileName, flags, new SftpFileAttributes(), handleAction, statusAction)
+        public SftpOpenRequest(uint protocolVersion, uint requestId, string fileName, Flags flags, Action<SftpHandleResponse> handleAction, Action<SftpStatusResponse> statusAction)
+            : this(protocolVersion, requestId, fileName, flags, new SftpFileAttributes(), handleAction, statusAction)
         {
         }
 
-        public SftpOpenRequest(uint requestId, string fileName, Flags flags, SftpFileAttributes attributes, Action<SftpHandleResponse> handleAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpOpenRequest(uint protocolVersion, uint requestId, string fileName, Flags flags, SftpFileAttributes attributes, Action<SftpHandleResponse> handleAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Filename = fileName;
             this.Flags = flags;

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public byte[] Handle { get; private set; }
 
-        public SftpReadDirRequest(uint requestId, byte[] handle, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpReadDirRequest(uint protocolVersion, uint requestId, byte[] handle, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Handle = handle;
             this.SetAction(nameAction);

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public SftpReadLinkRequest(uint requestId, string path, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpReadLinkRequest(uint protocolVersion, uint requestId, string path, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.SetAction(nameAction);

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

@@ -19,8 +19,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public UInt32 Length { get; private set; }
 
-        public SftpReadRequest(uint requestId, byte[] handle, UInt64 offset, UInt32 length, Action<SftpDataResponse> dataAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpReadRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt32 length, Action<SftpDataResponse> dataAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Handle = handle;
             this.Offset = offset;

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public SftpRealPathRequest(uint requestId, string path, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpRealPathRequest(uint protocolVersion, uint requestId, string path, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             if (nameAction == null)
                 throw new ArgumentNullException("name");

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Filename { get; private set; }
 
-        public SftpRemoveRequest(uint requestId, string filename, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpRemoveRequest(uint protocolVersion, uint requestId, string filename, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Filename = filename;
         }

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

@@ -17,8 +17,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string NewPath { get; private set; }
 
-        public SftpRenameRequest(uint requestId, string oldPath, string newPath, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.OldPath = oldPath;
             this.NewPath = newPath;

+ 4 - 1
Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpRequest.cs

@@ -17,10 +17,13 @@ namespace Renci.SshNet.Sftp.Requests
         private Action<SftpNameResponse> _nameAction;
 
         public uint RequestId { get; private set; }
+        
+        public uint ProtocolVersion { get; private set; }
 
-        public SftpRequest(uint requestId, Action<SftpStatusResponse> statusAction)
+        public SftpRequest(uint protocolVersion, uint requestId, Action<SftpStatusResponse> statusAction)
         {
             this.RequestId = requestId;
+            this.ProtocolVersion = protocolVersion;
             this._statusAction = statusAction;
         }
 

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public SftpRmDirRequest(uint requestId, string path, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpRmDirRequest(uint protocolVersion, uint requestId, string path, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
         }

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

@@ -17,8 +17,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public SftpFileAttributes Attributes { get; private set; }
 
-        public SftpSetStatRequest(uint requestId, string path, SftpFileAttributes attributes, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpSetStatRequest(uint protocolVersion, uint requestId, string path, SftpFileAttributes attributes, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.Attributes = attributes;

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

@@ -15,8 +15,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public SftpStatRequest(uint requestId, string path, Action<SftpAttrsResponse> attrsAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpStatRequest(uint protocolVersion, uint requestId, string path, Action<SftpAttrsResponse> attrsAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.SetAction(attrsAction);

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

@@ -17,8 +17,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string ExistingPath { get; set; }
 
-        public SftpSymLinkRequest(uint requestId, string newLinkPath, string existingPath, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpSymLinkRequest(uint protocolVersion, uint requestId, string newLinkPath, string existingPath, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.NewLinkPath = newLinkPath;
             this.ExistingPath = existingPath;

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

@@ -19,8 +19,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public byte[] Data { get; private set; }
 
-        public SftpWriteRequest(uint requestId, byte[] handle, UInt64 offset, byte[] data, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public SftpWriteRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, byte[] data, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Handle = handle;
             this.Offset = offset;

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

@@ -14,8 +14,8 @@ namespace Renci.SshNet.Sftp.Requests
 
         public string Path { get; private set; }
 
-        public StatVfsRequest(uint requestId, string path, Action<SftpExtendedReplyResponse> extendedAction, Action<SftpStatusResponse> statusAction)
-            : base(requestId, statusAction)
+        public StatVfsRequest(uint protocolVersion, uint requestId, string path, Action<SftpExtendedReplyResponse> extendedAction, Action<SftpStatusResponse> statusAction)
+            : base(protocolVersion, requestId, statusAction)
         {
             this.Path = path;
             this.SetAction(extendedAction);

+ 5 - 0
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpAttrsResponse.cs

@@ -14,6 +14,11 @@ namespace Renci.SshNet.Sftp.Responses
 
         public SftpFileAttributes Attributes { get; private set; }
 
+        public SftpAttrsResponse(uint protocolVersion)
+            : base(protocolVersion)
+        {
+        }
+
         protected override void LoadData()
         {
             base.LoadData();

+ 5 - 0
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpDataResponse.cs

@@ -16,6 +16,11 @@ namespace Renci.SshNet.Sftp.Responses
 
         public bool IsEof { get; set; }
 
+        public SftpDataResponse(uint protocolVersion)
+            : base(protocolVersion)
+        {
+        }
+
         protected override void LoadData()
         {
             base.LoadData();

+ 5 - 0
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpExtendedReplyResponse.cs

@@ -11,5 +11,10 @@ namespace Renci.SshNet.Sftp.Responses
         {
             get { return SftpMessageTypes.ExtendedReply; }
         }
+
+        public SftpExtendedReplyResponse(uint protocolVersion)
+            : base(protocolVersion)
+        {
+        }
     }
 }

+ 5 - 0
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpHandleResponse.cs

@@ -14,6 +14,11 @@ namespace Renci.SshNet.Sftp.Responses
 
         public byte[] Handle { get; private set; }
 
+        public SftpHandleResponse(uint protocolVersion)
+            : base(protocolVersion)
+        {
+        }
+
         protected override void LoadData()
         {
             base.LoadData();

+ 3 - 2
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpNameResponse.cs

@@ -16,9 +16,10 @@ namespace Renci.SshNet.Sftp.Responses
 
         public KeyValuePair<string, SftpFileAttributes>[] Files { get; private set; }
 
-        public SftpNameResponse()
+        public SftpNameResponse(uint protocolVersion)
+            : base(protocolVersion)
         {
-            this.Files = new KeyValuePair<string,SftpFileAttributes>[0];
+            this.Files = new KeyValuePair<string, SftpFileAttributes>[0];
         }
 
         protected override void LoadData()

+ 7 - 0
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpResponse.cs

@@ -9,6 +9,13 @@ namespace Renci.SshNet.Sftp.Responses
     {
         public uint ResponseId { get; private set; }
 
+        public uint ProtocolVersion { get; private set; }
+
+        public SftpResponse(uint protocolVersion)
+        {
+            this.ProtocolVersion = protocolVersion;
+        }
+
         protected override void LoadData()
         {
             base.LoadData();

+ 11 - 2
Renci.SshClient/Renci.SshNet/Sftp/Responses/SftpStatusResponse.cs

@@ -12,19 +12,28 @@ namespace Renci.SshNet.Sftp.Responses
             get { return SftpMessageTypes.Status; }
         }
 
+        public SftpStatusResponse(uint protocolVersion)
+            : base(protocolVersion)
+        {
+        }
 
         public StatusCodes StatusCode { get; private set; }
 
         public string ErrorMessage { get; private set; }
 
         public string Language { get; private set; }
-        
+
         protected override void LoadData()
         {
             base.LoadData();
-            
+
             this.StatusCode = (StatusCodes)this.ReadUInt32();
 
+            if (this.ProtocolVersion < 3)
+            {
+                return;
+            }
+
             if (!this.IsEndOfData)
             {
                 this.ErrorMessage = this.ReadString();

+ 5 - 0
Renci.SshClient/Renci.SshNet/Sftp/Responses/StatVfsResponse.cs

@@ -4,6 +4,11 @@
     {
         public SftpFileSytemInformation Information { get; private set; }
 
+        public StatVfsResponse()
+            : base(0)
+        {
+        }
+
         protected override void LoadData()
         {
             base.LoadData();

+ 9 - 9
Renci.SshClient/Renci.SshNet/Sftp/SftpMessage.cs

@@ -9,11 +9,11 @@ namespace Renci.SshNet.Sftp
 {
     internal abstract class SftpMessage : SshData
     {
-        public new static SftpMessage Load(byte[] data)
+        public new static SftpMessage Load(uint protocolVersion, byte[] data)
         {
             var messageType = (SftpMessageTypes)data.FirstOrDefault();
 
-            return Load(data, messageType);
+            return Load(protocolVersion, data, messageType);
         }
 
         protected override int ZeroReaderIndex
@@ -152,7 +152,7 @@ namespace Renci.SshNet.Sftp
             }
         }
 
-        private static SftpMessage Load(byte[] data, SftpMessageTypes messageType)
+        private static SftpMessage Load(uint protocolVersion, byte[] data, SftpMessageTypes messageType)
         {
             SftpMessage message = null;
 
@@ -162,22 +162,22 @@ namespace Renci.SshNet.Sftp
                     message = new SftpVersionResponse();
                     break;
                 case SftpMessageTypes.Status:
-                    message = new SftpStatusResponse();
+                    message = new SftpStatusResponse(protocolVersion);
                     break;
                 case SftpMessageTypes.Data:
-                    message = new SftpDataResponse();
+                    message = new SftpDataResponse(protocolVersion);
                     break;
                 case SftpMessageTypes.Handle:
-                    message = new SftpHandleResponse();
+                    message = new SftpHandleResponse(protocolVersion);
                     break;
                 case SftpMessageTypes.Name:
-                    message = new SftpNameResponse();
+                    message = new SftpNameResponse(protocolVersion);
                     break;
                 case SftpMessageTypes.Attrs:
-                    message = new SftpAttrsResponse();
+                    message = new SftpAttrsResponse(protocolVersion);
                     break;
                 case SftpMessageTypes.ExtendedReply:
-                    message = new SftpExtendedReplyResponse();
+                    message = new SftpExtendedReplyResponse(protocolVersion);
                     break;
                 default:
                     throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Message type '{0}' is not supported.", messageType));

+ 58 - 32
Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs

@@ -15,6 +15,10 @@ namespace Renci.SshNet.Sftp
 {
     internal class SftpSession : SubsystemSession
     {
+        private const int MAXIMUM_SUPPORTED_VERSION = 3;
+
+        private const int MINIMUM_SUPPORTED_VERSION = 0;
+
         private Dictionary<uint, SftpRequest> _requests = new Dictionary<uint, SftpRequest>();
 
         private List<byte> _data = new List<byte>(16 * 1024);
@@ -29,7 +33,7 @@ namespace Renci.SshNet.Sftp
         /// <summary>
         /// Gets SFTP protocol version.
         /// </summary>
-        public int ProtocolVersion { get; private set; }
+        public uint ProtocolVersion { get; private set; }
 
         private long _requestId;
         /// <summary>
@@ -164,11 +168,14 @@ namespace Renci.SshNet.Sftp
 
         protected override void OnChannelOpen()
         {
-            this.SendMessage(new SftpInitRequest(3));
+            this.SendMessage(new SftpInitRequest(MAXIMUM_SUPPORTED_VERSION));
 
             this.WaitHandle(this._sftpVersionConfirmed, this._operationTimeout);
 
-            this.ProtocolVersion = 3;
+            if (this.ProtocolVersion > MAXIMUM_SUPPORTED_VERSION || this.ProtocolVersion < MINIMUM_SUPPORTED_VERSION)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Server SFTP version {0} is not supported.", this.ProtocolVersion));
+            }
 
             //  Resolve current directory
             this.WorkingDirectory = this.RequestRealPath(".").First().Key;
@@ -202,21 +209,16 @@ namespace Renci.SshNet.Sftp
                 this._data.RemoveRange(0, packetLength);
 
                 //  Load SFTP Message and handle it
-                var response = SftpMessage.Load(packetData);
+                var response = SftpMessage.Load(this.ProtocolVersion, packetData);
 
                 try
                 {
                     var versionResponse = response as SftpVersionResponse;
                     if (versionResponse != null)
                     {
-                        if (versionResponse.Version == 3)
-                        {
-                            this._sftpVersionConfirmed.Set();
-                        }
-                        else
-                        {
-                            throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Server SFTP version {0} is not supported.", versionResponse.Version));
-                        }
+                        this.ProtocolVersion = versionResponse.Version;
+
+                        this._sftpVersionConfirmed.Set();
                     }
                     else
                     {
@@ -270,7 +272,7 @@ namespace Renci.SshNet.Sftp
 
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpOpenRequest(this.NextRequestId, path, flags,
+                var request = new SftpOpenRequest(this.ProtocolVersion, this.NextRequestId, path, flags,
                     (response) =>
                     {
                         handle = response.Handle;
@@ -304,7 +306,7 @@ namespace Renci.SshNet.Sftp
         {
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpCloseRequest(this.NextRequestId, handle,
+                var request = new SftpCloseRequest(this.ProtocolVersion, this.NextRequestId, handle,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -336,7 +338,7 @@ namespace Renci.SshNet.Sftp
 
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpReadRequest(this.NextRequestId, handle, offset, length,
+                var request = new SftpReadRequest(this.ProtocolVersion, this.NextRequestId, handle, offset, length,
                     (response) =>
                     {
                         data = response.Data;
@@ -371,7 +373,7 @@ namespace Renci.SshNet.Sftp
         /// <param name="wait">The wait event handle if needed.</param>
         internal void RequestWrite(byte[] handle, UInt64 offset, byte[] data, EventWaitHandle wait, Action<SftpStatusResponse> writeCompleted = null)
         {
-            var request = new SftpWriteRequest(this.NextRequestId, handle, offset, data,
+            var request = new SftpWriteRequest(this.ProtocolVersion, this.NextRequestId, handle, offset, data,
                 (response) =>
                 {
                     if (writeCompleted != null)
@@ -409,7 +411,7 @@ namespace Renci.SshNet.Sftp
             SftpFileAttributes attributes = null;
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpLStatRequest(this.NextRequestId, path,
+                var request = new SftpLStatRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         attributes = response.Attributes;
@@ -441,7 +443,7 @@ namespace Renci.SshNet.Sftp
             SftpFileAttributes attributes = null;
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpFStatRequest(this.NextRequestId, handle,
+                var request = new SftpFStatRequest(this.ProtocolVersion, this.NextRequestId, handle,
                     (response) =>
                     {
                         attributes = response.Attributes;
@@ -469,7 +471,7 @@ namespace Renci.SshNet.Sftp
         {
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpSetStatRequest(this.NextRequestId, path, attributes,
+                var request = new SftpSetStatRequest(this.ProtocolVersion, this.NextRequestId, path, attributes,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -497,7 +499,7 @@ namespace Renci.SshNet.Sftp
         {
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpFSetStatRequest(this.NextRequestId, handle, attributes,
+                var request = new SftpFSetStatRequest(this.ProtocolVersion, this.NextRequestId, handle, attributes,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -528,7 +530,7 @@ namespace Renci.SshNet.Sftp
 
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpOpenDirRequest(this.NextRequestId, path,
+                var request = new SftpOpenDirRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         handle = response.Handle;
@@ -565,7 +567,7 @@ namespace Renci.SshNet.Sftp
 
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpReadDirRequest(this.NextRequestId, handle,
+                var request = new SftpReadDirRequest(this.ProtocolVersion, this.NextRequestId, handle,
                     (response) =>
                     {
                         result = response.Files;
@@ -599,7 +601,7 @@ namespace Renci.SshNet.Sftp
         {
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpRemoveRequest(this.NextRequestId, path,
+                var request = new SftpRemoveRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -626,7 +628,7 @@ namespace Renci.SshNet.Sftp
         {
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpMkDirRequest(this.NextRequestId, path,
+                var request = new SftpMkDirRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -653,7 +655,7 @@ namespace Renci.SshNet.Sftp
         {
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpRmDirRequest(this.NextRequestId, path,
+                var request = new SftpRmDirRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -684,7 +686,7 @@ namespace Renci.SshNet.Sftp
 
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpRealPathRequest(this.NextRequestId, path,
+                var request = new SftpRealPathRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         result = response.Files;
@@ -724,7 +726,7 @@ namespace Renci.SshNet.Sftp
             SftpFileAttributes attributes = null;
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpStatRequest(this.NextRequestId, path,
+                var request = new SftpStatRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         attributes = response.Attributes;
@@ -757,9 +759,13 @@ namespace Renci.SshNet.Sftp
         /// <param name="newPath">The new path.</param>
         internal void RequestRename(string oldPath, string newPath)
         {
+            if (this.ProtocolVersion < 2)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_RENAME operation is not supported in {0} version that server operates in.", this.ProtocolVersion));
+            }
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpRenameRequest(this.NextRequestId, oldPath, newPath,
+                var request = new SftpRenameRequest(this.ProtocolVersion, this.NextRequestId, oldPath, newPath,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -786,11 +792,16 @@ namespace Renci.SshNet.Sftp
         /// <returns></returns>
         internal KeyValuePair<string, SftpFileAttributes>[] RequestReadLink(string path, bool nullOnError = false)
         {
+            if (this.ProtocolVersion < 3)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_READLINK operation is not supported in {0} version that server operates in.", this.ProtocolVersion));
+            }
+
             KeyValuePair<string, SftpFileAttributes>[] result = null;
 
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpReadLinkRequest(this.NextRequestId, path,
+                var request = new SftpReadLinkRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         result = response.Files;
@@ -824,9 +835,14 @@ namespace Renci.SshNet.Sftp
         /// <param name="targetpath">The targetpath.</param>
         internal void RequestSymLink(string linkpath, string targetpath)
         {
+            if (this.ProtocolVersion < 3)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_SYMLINK operation is not supported in {0} version that server operates in.", this.ProtocolVersion));
+            }
+
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new SftpSymLinkRequest(this.NextRequestId, linkpath, targetpath,
+                var request = new SftpSymLinkRequest(this.ProtocolVersion, this.NextRequestId, linkpath, targetpath,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -852,9 +868,14 @@ namespace Renci.SshNet.Sftp
         /// <param name="newPath">The new path.</param>
         internal void RequestPosixRename(string oldPath, string newPath)
         {
+            if (this.ProtocolVersion < 3)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", this.ProtocolVersion));
+            }
+
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new PosixRenameRequest(this.NextRequestId, oldPath, newPath,
+                var request = new PosixRenameRequest(this.ProtocolVersion, this.NextRequestId, oldPath, newPath,
                     (response) =>
                     {
                         if (response.StatusCode == StatusCodes.Ok)
@@ -881,10 +902,15 @@ namespace Renci.SshNet.Sftp
         /// <returns></returns>
         internal SftpFileSytemInformation RequestStatVfs(string path, bool nullOnError = false)
         {
+            if (this.ProtocolVersion < 3)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", this.ProtocolVersion));
+            }
+
             SftpFileSytemInformation information = null;
             using (var wait = new AutoResetEvent(false))
             {
-                var request = new StatVfsRequest(this.NextRequestId, path,
+                var request = new StatVfsRequest(this.ProtocolVersion, this.NextRequestId, path,
                     (response) =>
                     {
                         information = response.OfType<StatVfsResponse>().Information;

+ 1 - 1
Renci.SshClient/Renci.SshNet/SftpClient.cs

@@ -1448,7 +1448,7 @@ namespace Renci.SshNet
             this._sftpSession.Connect();
 
             //  Resolve current running version
-            this.ProtocolVersion = this._sftpSession.ProtocolVersion;
+            this.ProtocolVersion = (int)this._sftpSession.ProtocolVersion;
         }
 
         /// <summary>