using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Renci.SshNet.Abstractions;
using Renci.SshNet.Messages;
using Renci.SshNet.Messages.Connection;
namespace Renci.SshNet.Common
{
///
/// Collection of different extension method
///
internal static partial class Extensions
{
///
/// Determines whether [is null or white space] [the specified value].
///
/// The value.
///
/// true if [is null or white space] [the specified value]; otherwise, false.
///
internal static bool IsNullOrWhiteSpace(this string value)
{
if (string.IsNullOrEmpty(value)) return true;
return value.All(char.IsWhiteSpace);
}
internal static byte[] ToArray(this GlobalRequestName globalRequestName)
{
switch (globalRequestName)
{
case GlobalRequestName.TcpIpForward:
return SshData.Ascii.GetBytes("tcpip-forward");
case GlobalRequestName.CancelTcpIpForward:
return SshData.Ascii.GetBytes("cancel-tcpip-forward");
default:
throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", globalRequestName));
}
}
internal static byte[] ToArray(this ServiceName serviceName)
{
switch (serviceName)
{
case ServiceName.UserAuthentication:
return SshData.Ascii.GetBytes("ssh-userauth");
case ServiceName.Connection:
return SshData.Ascii.GetBytes("ssh-connection");
default:
throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", serviceName));
}
}
internal static ServiceName ToServiceName(this byte[] data)
{
var sshServiceName = SshData.Ascii.GetString(data, 0, data.Length);
switch (sshServiceName)
{
case "ssh-userauth":
return ServiceName.UserAuthentication;
case "ssh-connection":
return ServiceName.Connection;
default:
throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", sshServiceName));
}
}
internal static GlobalRequestName ToGlobalRequestName(this byte[] data)
{
var sshGlobalRequestName = SshData.Ascii.GetString(data, 0, data.Length);
switch (sshGlobalRequestName)
{
case "tcpip-forward":
return GlobalRequestName.TcpIpForward;
case "cancel-tcpip-forward":
return GlobalRequestName.CancelTcpIpForward;
default:
throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", sshGlobalRequestName));
}
}
internal static BigInteger ToBigInteger(this byte[] data)
{
var reversed = new byte[data.Length];
Buffer.BlockCopy(data, 0, reversed, 0, data.Length);
return new BigInteger(reversed.Reverse());
}
///
/// Reverses the sequence of the elements in the entire one-dimensional .
///
/// The one-dimensional to reverse.
///
/// The with its elements reversed.
///
internal static T[] Reverse(this T[] array)
{
Array.Reverse(array);
return array;
}
///
/// Checks whether a collection is the same as another collection
///
/// The current instance object
/// The collection to compare with
/// The comparer object to use to compare each item in the collection. If null uses EqualityComparer(T).Default
/// True if the two collections contain all the same items in the same order
internal static bool IsEqualTo(this IEnumerable value, IEnumerable compareList, IEqualityComparer comparer)
{
if (value == compareList)
return true;
if (value == null || compareList == null)
return false;
if (comparer == null)
{
comparer = EqualityComparer.Default;
}
var enumerator1 = value.GetEnumerator();
var enumerator2 = compareList.GetEnumerator();
var enum1HasValue = enumerator1.MoveNext();
var enum2HasValue = enumerator2.MoveNext();
try
{
while (enum1HasValue && enum2HasValue)
{
if (!comparer.Equals(enumerator1.Current, enumerator2.Current))
{
return false;
}
enum1HasValue = enumerator1.MoveNext();
enum2HasValue = enumerator2.MoveNext();
}
return !(enum1HasValue || enum2HasValue);
}
finally
{
enumerator1.Dispose();
enumerator2.Dispose();
}
}
///
/// Checks whether a collection is the same as another collection
///
/// The current instance object
/// The collection to compare with
/// True if the two collections contain all the same items in the same order
internal static bool IsEqualTo(this IEnumerable value, IEnumerable compareList)
{
return IsEqualTo(value, compareList, null);
}
///
/// Prints out
///
/// The bytes.
internal static void DebugPrint(this IEnumerable bytes)
{
var sb = new StringBuilder();
foreach (var b in bytes)
{
sb.AppendFormat(CultureInfo.CurrentCulture, "0x{0:x2}, ", b);
}
Debug.WriteLine(sb.ToString());
}
///
/// Trims the leading zero from bytes array.
///
/// The data.
/// Data without leading zeros.
internal static IEnumerable TrimLeadingZero(this IEnumerable data)
{
var leadingZero = true;
foreach (var item in data)
{
if (item == 0 & leadingZero)
{
continue;
}
leadingZero = false;
yield return item;
}
}
///
/// Creates an instance of the specified type using that type's default constructor.
///
/// The type to create.
/// Type of the instance to create.
/// A reference to the newly created object.
internal static T CreateInstance(this Type type) where T : class
{
if (type == null)
return null;
return Activator.CreateInstance(type) as T;
}
///
/// Returns the specified 16-bit unsigned integer value as an array of bytes.
///
/// The number to convert.
/// An array of bytes with length 2.
internal static byte[] GetBytes(this ushort value)
{
return new[] {(byte) (value >> 8), (byte) (value & 0xFF)};
}
///
/// Returns the specified 32-bit unsigned integer value as an array of bytes.
///
/// The number to convert.
/// An array of bytes with length 4.
internal static byte[] GetBytes(this uint value)
{
var buffer = new byte[4];
value.Write(buffer, 0);
return buffer;
}
///
/// Returns the specified 32-bit unsigned integer value as an array of bytes.
///
/// The number to convert.
/// The array of bytes to write to.
/// The zero-based offset in at which to begin writing.
internal static void Write(this uint value, byte[] buffer, int offset)
{
buffer[offset++] = (byte) (value >> 24);
buffer[offset++] = (byte) (value >> 16);
buffer[offset++] = (byte)(value >> 8);
buffer[offset] = (byte) (value & 0xFF);
}
///
/// Returns the specified 64-bit unsigned integer value as an array of bytes.
///
/// The number to convert.
/// An array of bytes with length 8.
internal static byte[] GetBytes(this ulong value)
{
return new[]
{
(byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
};
}
///
/// Returns the specified 64-bit signed integer value as an array of bytes.
///
/// The number to convert.
/// An array of bytes with length 8.
internal static byte[] GetBytes(this long value)
{
return new[]
{
(byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
};
}
internal static void ValidatePort(this uint value, string argument)
{
if (value > IPEndPoint.MaxPort)
throw new ArgumentOutOfRangeException(argument,
string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
IPEndPoint.MaxPort));
}
internal static void ValidatePort(this int value, string argument)
{
if (value < IPEndPoint.MinPort)
throw new ArgumentOutOfRangeException(argument,
string.Format(CultureInfo.InvariantCulture, "Specified value cannot be less than {0}.",
IPEndPoint.MinPort));
if (value > IPEndPoint.MaxPort)
throw new ArgumentOutOfRangeException(argument,
string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
IPEndPoint.MaxPort));
}
///
/// Returns a specified number of contiguous bytes from a given offset.
///
/// The array to return a number of bytes from.
/// The zero-based offset in at which to begin taking bytes.
/// The number of bytes to take from .
///
/// A array that contains the specified number of bytes at the specified offset
/// of the input array.
///
internal static byte[] Take(this byte[] data, int offset, int length)
{
var taken = new byte[length];
Buffer.BlockCopy(data, offset, taken, 0, length);
return taken;
}
internal static bool CanRead(this Socket socket)
{
return SocketAbstraction.CanRead(socket);
}
internal static bool CanWrite(this Socket socket)
{
return SocketAbstraction.CanWrite(socket);
}
}
}