mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 09:15:47 +00:00
Fix SFTP TODO items and some bug while downloading file.
This commit is contained in:
@@ -62,7 +62,7 @@ namespace Renci.SshClient.Channels
|
||||
|
||||
this.SendMessage(new InitMessage
|
||||
{
|
||||
Version = 6,
|
||||
Version = 3,
|
||||
});
|
||||
|
||||
var versionMessage = this.ReceiveMessage<VersionMessage>();
|
||||
@@ -128,7 +128,7 @@ namespace Renci.SshClient.Channels
|
||||
while ((data = this.RemoteRead(handle, offset, bufferSize)) != null)
|
||||
{
|
||||
var fileData = data.GetSshBytes().ToArray();
|
||||
destination.Write(fileData, 0, (int)bufferSize);
|
||||
destination.Write(fileData, 0, fileData.Length);
|
||||
destination.Flush();
|
||||
offset += (ulong)fileData.Length;
|
||||
}
|
||||
@@ -216,6 +216,7 @@ namespace Renci.SshClient.Channels
|
||||
this._channelRequestSuccessWaitHandle.Set();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnChannelData(string data)
|
||||
{
|
||||
base.OnChannelData(data);
|
||||
@@ -243,8 +244,15 @@ namespace Renci.SshClient.Channels
|
||||
|
||||
this._packetData = null;
|
||||
|
||||
// TODO: Handle SSH_FXP_STATUS here
|
||||
// TODO: Validate message request id is correct
|
||||
if (sftpMessage.RequestId != null)
|
||||
{
|
||||
if (sftpMessage.RequestId != this._requestId)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid request id.");
|
||||
}
|
||||
|
||||
this._requestId++;
|
||||
}
|
||||
|
||||
this._responseMessage = sftpMessage;
|
||||
|
||||
@@ -302,7 +310,7 @@ namespace Renci.SshClient.Channels
|
||||
|
||||
private void SendMessage(SftpMessage sftpMessage)
|
||||
{
|
||||
sftpMessage.RequestId = this._requestId++;
|
||||
sftpMessage.RequestId = this._requestId;
|
||||
var message = new SftpDataMessage
|
||||
{
|
||||
ChannelNumber = this.ServerChannelNumber,
|
||||
@@ -465,7 +473,18 @@ namespace Renci.SshClient.Channels
|
||||
});
|
||||
|
||||
var status = this.ReceiveMessage<StatusMessage>();
|
||||
// TODO: If close is fails wait a litle a try to close it again, in case server fluashed data into the file during close
|
||||
var attempts = 0;
|
||||
// If close is fails wait a litle a try to close it again, in case server flushed data into the file during close
|
||||
while (status.StatusCode != StatusCodes.Ok && attempts++ < this.Session.ConnectionInfo.RetryAttempts)
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
status = this.ReceiveMessage<StatusMessage>();
|
||||
}
|
||||
|
||||
if (status.StatusCode != StatusCodes.Ok)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("File handle cannot be closed after {0} attempts.", attempts));
|
||||
}
|
||||
}
|
||||
|
||||
private Attributes GetRemoteFileAttributes(string filename)
|
||||
|
||||
@@ -9,19 +9,19 @@ namespace Renci.SshClient.Common
|
||||
|
||||
public string FullName { get; set; }
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
public DateTime? CreationTime { get; set; }
|
||||
|
||||
public DateTime LastAccessTime { get; set; }
|
||||
public DateTime? LastAccessTime { get; set; }
|
||||
|
||||
public DateTime LastModifyTime { get; set; }
|
||||
public DateTime? LastModifyTime { get; set; }
|
||||
|
||||
public ulong Size { get; set; }
|
||||
public ulong? Size { get; set; }
|
||||
|
||||
public uint UserId { get; set; }
|
||||
public uint? UserId { get; set; }
|
||||
|
||||
public uint GroupId { get; set; }
|
||||
public uint? GroupId { get; set; }
|
||||
|
||||
public uint Permissions { get; set; }
|
||||
public uint? Permissions { get; set; }
|
||||
|
||||
public IDictionary<string, string> Extentions { get; set; }
|
||||
|
||||
|
||||
@@ -5,19 +5,17 @@ namespace Renci.SshClient.Messages.Sftp
|
||||
{
|
||||
internal class Attributes
|
||||
{
|
||||
public UInt32 Flag { get; set; }
|
||||
public ulong? Size { get; set; }
|
||||
|
||||
public ulong Size { get; set; }
|
||||
public uint? UserId { get; set; }
|
||||
|
||||
public uint UserId { get; set; }
|
||||
public uint? GroupId { get; set; }
|
||||
|
||||
public uint GroupId { get; set; }
|
||||
public uint? Permissions { get; set; }
|
||||
|
||||
public uint Permissions { get; set; }
|
||||
public DateTime? AccessTime { get; set; }
|
||||
|
||||
public DateTime AccessTime { get; set; }
|
||||
|
||||
public DateTime ModifyTime { get; set; }
|
||||
public DateTime? ModifyTime { get; set; }
|
||||
|
||||
public IDictionary<string, string> Extentions { get; set; }
|
||||
}
|
||||
|
||||
@@ -72,33 +72,27 @@ namespace Renci.SshClient.Messages.Sftp
|
||||
protected Attributes ReadAttributes()
|
||||
{
|
||||
var attributes = new Attributes();
|
||||
attributes.Flag = this.ReadUInt32();
|
||||
|
||||
var isSize = (attributes.Flag & 0x00000001) == 0x00000001; //SSH_FILEXFER_ATTR_SIZE 0x00000001
|
||||
var isUidGid = (attributes.Flag & 0x00000002) == 0x00000002; //SSH_FILEXFER_ATTR_UIDGID 0x00000002
|
||||
var isPermissions = (attributes.Flag & 0x00000004) == 0x00000004; //SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
|
||||
var isAccessModifyTime = (attributes.Flag & 0x00000008) == 0x00000008; //SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
|
||||
var flag = this.ReadUInt32();
|
||||
|
||||
var isExtended = (attributes.Flag & 0x80000000) == 0x80000000; //SSH_FILEXFER_ATTR_EXTENDED 0x80000000
|
||||
|
||||
if (isSize)
|
||||
if ((flag & 0x00000001) == 0x00000001) // SSH_FILEXFER_ATTR_SIZE
|
||||
{
|
||||
attributes.Size = this.ReadUInt64();
|
||||
}
|
||||
|
||||
if (isUidGid)
|
||||
if ((flag & 0x00000002) == 0x00000002) // SSH_FILEXFER_ATTR_UIDGID
|
||||
{
|
||||
attributes.UserId = this.ReadUInt32();
|
||||
|
||||
attributes.GroupId = this.ReadUInt32();
|
||||
}
|
||||
|
||||
if (isPermissions)
|
||||
if ((flag & 0x00000004) == 0x00000004) // SSH_FILEXFER_ATTR_PERMISSIONS
|
||||
{
|
||||
attributes.Permissions = this.ReadUInt32();
|
||||
}
|
||||
|
||||
if (isAccessModifyTime)
|
||||
if ((flag & 0x00000008) == 0x00000008) // SSH_FILEXFER_ATTR_ACMODTIME
|
||||
{
|
||||
var time = this.ReadUInt32();
|
||||
attributes.AccessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
|
||||
@@ -106,7 +100,7 @@ namespace Renci.SshClient.Messages.Sftp
|
||||
attributes.ModifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
|
||||
}
|
||||
|
||||
if (isExtended)
|
||||
if ((flag & 0x80000000) == 0x80000000) // SSH_FILEXFER_ATTR_ACMODTIME
|
||||
{
|
||||
var extendedCount = this.ReadUInt32();
|
||||
attributes.Extentions = this.ReadExtensionPair();
|
||||
@@ -117,7 +111,6 @@ namespace Renci.SshClient.Messages.Sftp
|
||||
|
||||
protected void Write(Attributes attributes)
|
||||
{
|
||||
// TODO: Complete attribute serialization, at this point we pass no attributes
|
||||
if (attributes == null)
|
||||
{
|
||||
this.Write((uint)0);
|
||||
@@ -125,42 +118,60 @@ namespace Renci.SshClient.Messages.Sftp
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Need to be tested
|
||||
throw new NotImplementedException();
|
||||
UInt32 flag = 0;
|
||||
|
||||
var isSize = (attributes.Flag & 0x00000001) == 0x00000001; //SSH_FILEXFER_ATTR_SIZE 0x00000001
|
||||
var isUidGid = (attributes.Flag & 0x00000002) == 0x00000002; //SSH_FILEXFER_ATTR_UIDGID 0x00000002
|
||||
var isPermissions = (attributes.Flag & 0x00000004) == 0x00000004; //SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
|
||||
var isAccessModifyTime = (attributes.Flag & 0x00000008) == 0x00000008; //SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
|
||||
|
||||
var isExtended = (attributes.Flag & 0x80000000) == 0x80000000; //SSH_FILEXFER_ATTR_EXTENDED 0x80000000
|
||||
|
||||
if (isSize)
|
||||
if (attributes.Size.HasValue)
|
||||
{
|
||||
this.Write(attributes.Size);
|
||||
flag |= 0x00000001;
|
||||
}
|
||||
|
||||
if (isUidGid)
|
||||
if (attributes.UserId.HasValue && attributes.GroupId.HasValue)
|
||||
{
|
||||
this.Write(attributes.UserId);
|
||||
|
||||
this.Write(attributes.GroupId);
|
||||
flag |= 0x00000002;
|
||||
}
|
||||
|
||||
if (isPermissions)
|
||||
if (attributes.Permissions.HasValue)
|
||||
{
|
||||
this.Write(attributes.Permissions);
|
||||
flag |= 0x00000004;
|
||||
}
|
||||
|
||||
if (isAccessModifyTime)
|
||||
if (attributes.AccessTime.HasValue && attributes.ModifyTime.HasValue)
|
||||
{
|
||||
uint time = (uint)(attributes.AccessTime.ToFileTime() - 11644473600) / 10000000;
|
||||
flag |= 0x00000008;
|
||||
}
|
||||
|
||||
if (attributes.Extentions != null)
|
||||
{
|
||||
flag |= 0x80000000;
|
||||
}
|
||||
|
||||
this.Write(flag);
|
||||
|
||||
if (attributes.Size.HasValue)
|
||||
{
|
||||
this.Write(attributes.Size.Value);
|
||||
}
|
||||
|
||||
if (attributes.UserId.HasValue && attributes.GroupId.HasValue)
|
||||
{
|
||||
this.Write(attributes.UserId.Value);
|
||||
this.Write(attributes.GroupId.Value);
|
||||
}
|
||||
|
||||
if (attributes.Permissions.HasValue)
|
||||
{
|
||||
this.Write(attributes.Permissions.Value);
|
||||
}
|
||||
|
||||
if (attributes.AccessTime.HasValue && attributes.ModifyTime.HasValue)
|
||||
{
|
||||
uint time = (uint)(attributes.AccessTime.Value.ToFileTime() / 10000000 - 11644473600);
|
||||
this.Write(time);
|
||||
time = (uint)(attributes.ModifyTime.ToFileTime() - 11644473600) / 10000000;
|
||||
time = (uint)(attributes.ModifyTime.Value.ToFileTime() / 10000000 - 11644473600);
|
||||
this.Write(time);
|
||||
}
|
||||
|
||||
if (isExtended)
|
||||
if (attributes.Extentions != null)
|
||||
{
|
||||
this.Write(attributes.Extentions);
|
||||
}
|
||||
|
||||
@@ -47,21 +47,17 @@
|
||||
this.ErrorMessage = this.ReadString();
|
||||
this.Language = this.ReadString();
|
||||
}
|
||||
// TODO: Load error specific data
|
||||
}
|
||||
|
||||
protected override void SaveData()
|
||||
{
|
||||
base.SaveData();
|
||||
this.Write((uint)this.StatusCode);
|
||||
if (this.StatusCode == StatusCodes.Ok)
|
||||
if (!string.IsNullOrEmpty(this.ErrorMessage))
|
||||
{
|
||||
// No more data need to be written
|
||||
return;
|
||||
this.Write(this.ErrorMessage);
|
||||
this.Write(this.Language);
|
||||
}
|
||||
this.Write(this.ErrorMessage);
|
||||
this.Write(this.Language);
|
||||
// TODO: Save error specific data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user