2
0

SftpMessage.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Renci.SshNet.Common;
  5. using System.Globalization;
  6. using Renci.SshNet.Sftp.Responses;
  7. using System.Text;
  8. namespace Renci.SshNet.Sftp
  9. {
  10. internal abstract class SftpMessage : SshData
  11. {
  12. public static SftpMessage Load(uint protocolVersion, byte[] data, Encoding encoding)
  13. {
  14. var messageType = (SftpMessageTypes)data.FirstOrDefault();
  15. return Load(protocolVersion, data, messageType, encoding);
  16. }
  17. protected override int ZeroReaderIndex
  18. {
  19. get
  20. {
  21. return 1;
  22. }
  23. }
  24. public abstract SftpMessageTypes SftpMessageType { get; }
  25. protected override void LoadData()
  26. {
  27. }
  28. protected override void SaveData()
  29. {
  30. this.Write((byte)this.SftpMessageType);
  31. }
  32. protected SftpFileAttributes ReadAttributes()
  33. {
  34. var flag = this.ReadUInt32();
  35. long size = -1;
  36. int userId = -1;
  37. int groupId = -1;
  38. uint permissions = 0;
  39. var accessTime = DateTime.MinValue;
  40. var modifyTime = DateTime.MinValue;
  41. IDictionary<string, string> extensions = null;
  42. if ((flag & 0x00000001) == 0x00000001) // SSH_FILEXFER_ATTR_SIZE
  43. {
  44. size = (long)this.ReadUInt64();
  45. }
  46. if ((flag & 0x00000002) == 0x00000002) // SSH_FILEXFER_ATTR_UIDGID
  47. {
  48. userId = (int)this.ReadUInt32();
  49. groupId = (int)this.ReadUInt32();
  50. }
  51. if ((flag & 0x00000004) == 0x00000004) // SSH_FILEXFER_ATTR_PERMISSIONS
  52. {
  53. permissions = this.ReadUInt32();
  54. }
  55. if ((flag & 0x00000008) == 0x00000008) // SSH_FILEXFER_ATTR_ACMODTIME
  56. {
  57. var time = this.ReadUInt32();
  58. accessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
  59. time = this.ReadUInt32();
  60. modifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
  61. }
  62. if ((flag & 0x80000000) == 0x80000000) // SSH_FILEXFER_ATTR_ACMODTIME
  63. {
  64. var extendedCount = this.ReadUInt32();
  65. extensions = this.ReadExtensionPair();
  66. }
  67. var attributes = new SftpFileAttributes(accessTime, modifyTime, size, userId, groupId, permissions, extensions);
  68. return attributes;
  69. }
  70. protected void Write(SftpFileAttributes attributes)
  71. {
  72. if (attributes == null)
  73. {
  74. this.Write((uint)0);
  75. return;
  76. }
  77. UInt32 flag = 0;
  78. if (attributes.IsSizeChanged && attributes.IsRegularFile)
  79. {
  80. flag |= 0x00000001;
  81. }
  82. if (attributes.IsUserIdChanged|| attributes.IsGroupIdChanged)
  83. {
  84. flag |= 0x00000002;
  85. }
  86. if (attributes.IsPermissionsChanged)
  87. {
  88. flag |= 0x00000004;
  89. }
  90. if (attributes.IsLastAccessTimeChanged || attributes.IsLastWriteTimeChanged)
  91. {
  92. flag |= 0x00000008;
  93. }
  94. if (attributes.IsExtensionsChanged)
  95. {
  96. flag |= 0x80000000;
  97. }
  98. this.Write(flag);
  99. if (attributes.IsSizeChanged && attributes.IsRegularFile)
  100. {
  101. this.Write((UInt64)attributes.Size);
  102. }
  103. if (attributes.IsUserIdChanged|| attributes.IsGroupIdChanged)
  104. {
  105. this.Write((UInt32)attributes.UserId);
  106. this.Write((UInt32)attributes.GroupId);
  107. }
  108. if (attributes.IsPermissionsChanged)
  109. {
  110. this.Write(attributes.Permissions);
  111. }
  112. if (attributes.IsLastAccessTimeChanged || attributes.IsLastWriteTimeChanged)
  113. {
  114. var time = (uint)(attributes.LastAccessTime.ToFileTime() / 10000000 - 11644473600);
  115. this.Write(time);
  116. time = (uint)(attributes.LastWriteTime.ToFileTime() / 10000000 - 11644473600);
  117. this.Write(time);
  118. }
  119. if (attributes.IsExtensionsChanged)
  120. {
  121. this.Write(attributes.Extensions);
  122. }
  123. }
  124. private static SftpMessage Load(uint protocolVersion, byte[] data, SftpMessageTypes messageType, Encoding encoding)
  125. {
  126. SftpMessage message;
  127. switch (messageType)
  128. {
  129. case SftpMessageTypes.Version:
  130. message = new SftpVersionResponse();
  131. break;
  132. case SftpMessageTypes.Status:
  133. message = new SftpStatusResponse(protocolVersion);
  134. break;
  135. case SftpMessageTypes.Data:
  136. message = new SftpDataResponse(protocolVersion);
  137. break;
  138. case SftpMessageTypes.Handle:
  139. message = new SftpHandleResponse(protocolVersion);
  140. break;
  141. case SftpMessageTypes.Name:
  142. message = new SftpNameResponse(protocolVersion, encoding);
  143. break;
  144. case SftpMessageTypes.Attrs:
  145. message = new SftpAttrsResponse(protocolVersion);
  146. break;
  147. case SftpMessageTypes.ExtendedReply:
  148. message = new SftpExtendedReplyResponse(protocolVersion);
  149. break;
  150. default:
  151. throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Message type '{0}' is not supported.", messageType));
  152. }
  153. message.LoadBytes(data);
  154. message.ResetReader();
  155. message.LoadData();
  156. return message;
  157. }
  158. public override string ToString()
  159. {
  160. return string.Format(CultureInfo.CurrentCulture, "SFTP Message : {0}", this.SftpMessageType);
  161. }
  162. }
  163. }