diff --git a/src/Renci.SshNet/ScpClient.cs b/src/Renci.SshNet/ScpClient.cs
index dfdec27c9..d08d624bd 100644
--- a/src/Renci.SshNet/ScpClient.cs
+++ b/src/Renci.SshNet/ScpClient.cs
@@ -1,11 +1,11 @@
using System;
-using System.Text;
using Renci.SshNet.Channels;
using System.IO;
using Renci.SshNet.Common;
using System.Text.RegularExpressions;
using System.Diagnostics.CodeAnalysis;
using System.Net;
+using System.Collections.Generic;
namespace Renci.SshNet
{
@@ -13,13 +13,23 @@ namespace Renci.SshNet
/// Provides SCP client functionality.
///
///
+ ///
/// More information on the SCP protocol is available here:
/// https://github.com/net-ssh/net-scp/blob/master/lib/net/scp.rb
+ ///
+ ///
+ /// Known issues in OpenSSH:
+ ///
+ /// -
+ /// Recursive download (-prf) does not deal well with specific UTF-8 and newline characters.
+ /// Recursive update does not support empty path for uploading to home directorydeal well with specific UTF-8 and newline characters.
+ ///
+ ///
+ ///
///
public partial class ScpClient : BaseClient
{
private static readonly Regex FileInfoRe = new Regex(@"C(?\d{4}) (?\d+) (?.+)");
- private static char[] _byteToChar;
///
/// Gets or sets the operation timeout.
@@ -150,16 +160,6 @@ internal ScpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServ
{
OperationTimeout = SshNet.Session.InfiniteTimeSpan;
BufferSize = 1024 * 16;
-
- if (_byteToChar == null)
- {
- _byteToChar = new char[128];
- var ch = '\0';
- for (var i = 0; i < 128; i++)
- {
- _byteToChar[i] = ch++;
- }
- }
}
#endregion
@@ -243,7 +243,7 @@ public void Download(string filename, Stream destination)
}
}
- private static void InternalSetTimestamp(IChannelSession channel, Stream input, DateTime lastWriteTime, DateTime lastAccessime)
+ private void InternalSetTimestamp(IChannelSession channel, Stream input, DateTime lastWriteTime, DateTime lastAccessime)
{
var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var modificationSeconds = (long) (lastWriteTime - zeroTime).TotalSeconds;
@@ -329,7 +329,7 @@ private static void SendConfirmation(IChannel channel)
SendData(channel, new byte[] { 0 });
}
- private static void SendConfirmation(IChannel channel, byte errorCode, string message)
+ private void SendConfirmation(IChannel channel, byte errorCode, string message)
{
SendData(channel, new[] { errorCode });
SendData(channel, string.Format("{0}\n", message));
@@ -339,7 +339,7 @@ private static void SendConfirmation(IChannel channel, byte errorCode, string me
/// Checks the return code.
///
/// The output stream.
- private static void CheckReturnCode(Stream input)
+ private void CheckReturnCode(Stream input)
{
var b = ReadByte(input);
@@ -351,9 +351,9 @@ private static void CheckReturnCode(Stream input)
}
}
- private static void SendData(IChannel channel, string command)
+ private void SendData(IChannel channel, string command)
{
- channel.SendData(SshData.Utf8.GetBytes(command));
+ channel.SendData(ConnectionInfo.Encoding.GetBytes(command));
}
private static void SendData(IChannel channel, byte[] buffer, int length)
@@ -374,35 +374,36 @@ private static int ReadByte(Stream stream)
return b;
}
- private static string ReadString(Stream stream)
+ ///
+ /// Read a LF-terminated string from the .
+ ///
+ /// The to read from.
+ ///
+ /// The string without trailing LF.
+ ///
+ private string ReadString(Stream stream)
{
var hasError = false;
- var sb = new StringBuilder();
+ var buffer = new List();
var b = ReadByte(stream);
-
if (b == 1 || b == 2)
{
hasError = true;
b = ReadByte(stream);
}
- var ch = _byteToChar[b];
-
- while (ch != '\n')
+ while (b != SshNet.Session.LineFeed)
{
- sb.Append(ch);
-
+ buffer.Add((byte) b);
b = ReadByte(stream);
-
- ch = _byteToChar[b];
}
if (hasError)
- throw new ScpException(sb.ToString());
+ throw new ScpException(ConnectionInfo.Encoding.GetString(buffer.ToArray()));
- return sb.ToString();
+ return ConnectionInfo.Encoding.GetString(buffer.ToArray());
}
}
}
diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs
index ac929685c..1f5f4eb2a 100644
--- a/src/Renci.SshNet/Session.cs
+++ b/src/Renci.SshNet/Session.cs
@@ -28,7 +28,7 @@ public class Session : ISession
{
private const byte Null = 0x00;
private const byte CarriageReturn = 0x0d;
- private const byte LineFeed = 0x0a;
+ internal const byte LineFeed = 0x0a;
///
/// Specifies an infinite waiting period.