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); } } }