diff --git a/IPv6 Test Cases.docx b/IPv6 Test Cases.docx new file mode 100644 index 00000000..fd7ecedf Binary files /dev/null and b/IPv6 Test Cases.docx differ diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/App.config b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/App.config index 60bc4b39..18e7f2ee 100644 --- a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/App.config +++ b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/App.config @@ -9,7 +9,7 @@ - + diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe index 310afe24..19904b01 100644 Binary files a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe and b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe differ diff --git a/WebsitePanel/Sources/VersionInfo.cs b/WebsitePanel/Sources/VersionInfo.cs index 5a84a297..dc1dff42 100644 --- a/WebsitePanel/Sources/VersionInfo.cs +++ b/WebsitePanel/Sources/VersionInfo.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.269 +// Runtime Version:4.0.30319.17929 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/WebsitePanel/Sources/VersionInfo.vb b/WebsitePanel/Sources/VersionInfo.vb index 10e75385..0f49fca3 100644 --- a/WebsitePanel/Sources/VersionInfo.vb +++ b/WebsitePanel/Sources/VersionInfo.vb @@ -1,7 +1,7 @@ '------------------------------------------------------------------------------ ' ' This code was generated by a tool. -' Runtime Version:4.0.30319.269 +' Runtime Version:4.0.30319.17929 ' ' Changes to this file may cause incorrect behavior and will be lost if ' the code is regenerated. diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln index fb708ef8..9ace796d 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln @@ -1,16 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C57D3F9F-7BA0-4D38-A159-B6EDA5C19B13}" - ProjectSection(SolutionItems) = preProject - ..\Database\install_db.sql = ..\Database\install_db.sql - ..\..\LICENSE.txt = ..\..\LICENSE.txt - ..\..\Readme.htm = ..\..\Readme.htm - ..\..\ReleaseNotes.htm = ..\..\ReleaseNotes.htm - ..\Database\update_db.sql = ..\Database\update_db.sql - VersionInfo.cs = VersionInfo.cs - VersionInfo.vb = VersionInfo.vb - EndProjectSection -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.EnterpriseServer", "WebsitePanel.EnterpriseServer\WebsitePanel.EnterpriseServer.csproj", "{59C7623A-5181-48A5-880A-C9B82B48F589}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.EnterpriseServer.Base", "WebsitePanel.EnterpriseServer.Base\WebsitePanel.EnterpriseServer.Base.csproj", "{C09CE910-F16B-48A1-B2CC-C99B8C1CF775}" diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Common/IPAddress.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Common/IPAddress.cs new file mode 100644 index 00000000..5135bfc6 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Common/IPAddress.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace WebsitePanel.EnterpriseServer { + + public struct IPAddress { + public Int128 Address; + public bool V6 { get; private set; } + public bool V4 { get { return !V6 || Null; } } + public bool IsSubnet { get; private set; } + public bool IsMask { get; private set; } + public int Cidr { get; private set; } + public bool Null { get; private set; } + public IPAddress LastSubnetIP { get { return new IPAddress { Address = (Address | (~((Int128)0) >> (V4 ? Cidr + 64 : Cidr))), Cidr = V4 ? 32 : 128, IsSubnet = false, Null = false, V6 = V6 }; } } + public IPAddress FirstSubnetIP { get { return new IPAddress { Address = (Address & ~(~((Int128)0) >> (V4 ? Cidr + 64 : Cidr))) + 1, Cidr = V4 ? 32 : 128, IsSubnet = false, Null = false, V6 = V6 }; } } + public Int128 Mask { get { return IsSubnet ? Int128.MinValue >> (Cidr-1) : Address; } } + + const int c = 256*256; + + public static IPAddress Parse(string ip) + { + IPAddress adr = default(IPAddress); + adr.V6 = false; + + if (String.IsNullOrEmpty(ip)) { + adr.Address = 0; adr.Null = true; adr.Cidr = 32; adr.IsSubnet = false; + return adr; + } + + if (ip.Contains('/')) { + var tokens = ip.Split('/'); + ip = tokens[0]; + adr.IsSubnet = true; + adr.Cidr = Utils.ParseInt(tokens[1], -1); + } + + if (string.IsNullOrWhiteSpace(ip)) { + adr.IsMask = true; adr.V6 = true; + adr.Address = adr.Mask; + } else { + + var ipadr = System.Net.IPAddress.Parse(ip); + + if (adr.V6 = ipadr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { + byte[] bytes = ipadr.GetAddressBytes(); + Int128 a = 0; + for (int i = 0; i < 16; i++) { + a = a * 256 + bytes[i]; + } + adr.Address = a; + } else { + string[] parts = ip.Split('.'); + adr.Address = (Int128)(Int32.Parse(parts[3]) + + (Int32.Parse(parts[2]) << 8) + + (Int32.Parse(parts[1]) << 16) + + (Int32.Parse(parts[0]) << 24)); + } + } + if (adr.V4 && (adr.Cidr > 32 || 0 > adr.Cidr)) throw new ArgumentOutOfRangeException("Cidr must not be greater than 32 for IPv4 Addresses."); + if (adr.V6 && (adr.Cidr > 128 || 0 > adr.Cidr)) throw new ArgumentOutOfRangeException("Cidr must not be greater than 128 for IPv6 Addresses."); + return adr; + } + + public override string ToString() + { + if (Null) + return ""; + var s = new System.Text.StringBuilder(); + if (!V6) { + var ipl = (long)Address; + s.Append(String.Format("{0}.{1}.{2}.{3}", (ipl >> 24) & 0xFFL, (ipl >> 16) & 0xFFL, (ipl >> 8) & 0xFFL, (ipl & 0xFFL))); + } else if (!IsMask) { + + var vals = new List(); + int i; + Int128 a = Address; + for (i = 0; i < 8; i++) { + vals.Add((int)(a % c)); + a = a / c; + } + + int index = -1, n = 0, m = 0; + for (i = 7; i >= 0; i--) { + if (vals[i] == 0) { + n++; + if (n > m) { + index = i; + m = n; + } + } + } + index += m-1; + + i = 7; + while (i >= 0) { + if (i == index) { + if (m == 8) s.Append("::"); + else s.Append(":"); + i -= m; + } + if (i >= 0) { + if (i < 7) s.Append(":"); + s.Append(vals[i].ToString("x")); + } + i--; + } + } + if (IsSubnet && !(IsMask && V4)) { + s.Append('/'); s.Append(Cidr.ToString()); + } + return s.ToString(); + } + + public string ToV4MaskString() { + V6 = false; + IsMask = true; + return ToString(); + } + + public static bool operator ==(IPAddress a, IPAddress b) { return a.Address == b.Address && a.Null == b.Null && (a.Null || !(a.IsSubnet && b.IsSubnet || a.IsMask && b.IsMask) || a.Cidr == b.Cidr); } + public static bool operator ==(IPAddress a, long b) { return a.Address == b; } + public static bool operator !=(IPAddress a, IPAddress b) { return !(a == b); } + public static bool operator !=(IPAddress a, long b) { return a.Address != b; } + public static bool operator <(IPAddress a, IPAddress b) { return a.Address < b.Address; } + public static bool operator >(IPAddress a, IPAddress b) { return a.Address > b.Address; } + public static bool operator <=(IPAddress a, IPAddress b) { return a.Address <= b.Address; } + public static bool operator >=(IPAddress a, IPAddress b) { return a.Address >= b.Address; } + /* + public static IPAddress operator +(IPAddress a, IPAddress b) { + if (a.IsSubnet || b.IsSubnet || a.V6 != b.V6) throw new ArgumentException("Arithmetic with subnets or mixed v4 & v6 addresses not supported."); + return new IPAddress { Address = a.Address + b.Address, Null = a.Null && b.Null, Cidr = 0, V6 = a.V6 }; + }*/ + + public static Int128 operator -(IPAddress a, IPAddress b) { + if (a.IsSubnet || b.IsSubnet || a.V6 != b.V6) throw new ArgumentException("Arithmetic with subnets or mixed v4 & v6 addresses not supported."); + return a.Address - b.Address; + } + public static IPAddress operator +(IPAddress a, Int128 b) { + return new IPAddress { Address = a.Address + b, Null = a.Null, Cidr = a.V4 ? 32 : 128, V6 = a.V6 }; + } + public static IPAddress operator -(IPAddress a, Int128 b) { + return new IPAddress { Address = a.Address - b, Null = a.Null, Cidr = a.V4 ? 32 : 128, V6 = a.V6 }; + } + public static IPAddress operator |(IPAddress a, IPAddress b) { + if (a.V6 != b.V6) throw new ArgumentException("Arithmetic with mixed v4 & v6 addresses not supported."); + return new IPAddress { Address = a.Address | b.Address, Cidr = a.V4 ? 32 : 128, Null = false, V6 = a.V6, IsSubnet = false }; + } + public static IPAddress operator &(IPAddress a, IPAddress b) { + if (a.V6 != b.V6) throw new ArgumentException("Arithmetic with mixed v4 & v6 addresses not supported."); + return new IPAddress { Address = a.Address | b.Address, Cidr = a.V4 ? 32 : 128, Null = false, V6 = a.V6, IsSubnet = false }; + } + public static IPAddress operator ~(IPAddress a) { + if (a.Null) return new IPAddress { Address = 0, Null = true, Cidr = a.V4 ? 32 : 128, V6 = true, IsSubnet = false }; + return new IPAddress { Address = ~a.Address, Cidr = a.Cidr , Null = false, V6 = a.V6, IsSubnet = false }; + } + + public static implicit operator IPAddress(NullIPAddress a) { return new IPAddress { Null = true, Address = 0, Cidr = -1 }; } + } + + public class NullIPAddress { } + +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Common/Int128.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Common/Int128.cs new file mode 100644 index 00000000..6df29285 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Common/Int128.cs @@ -0,0 +1,2198 @@ +/* + * Int128.c: Represents a 128-bit signed integer. + * + * Authors: + * Simon Mourier + * + * Copyright 2010-2012 SoftFluent S.A.S, (http://www.softfluent.com) + */ + +using System; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +#if !WINDOWS_PHONE && !SILVERLIGHT +using Microsoft.SqlServer.Server; +#endif + +namespace WebsitePanel.EnterpriseServer +{ + /// + /// Represents a 128-bit signed integer. + /// +#if !WINDOWS_PHONE && !SILVERLIGHT + [Serializable] +#endif + [StructLayout(LayoutKind.Sequential)] + [TypeConverter(typeof(Int128Converter))] + public struct Int128 : IComparable, IComparable, IEquatable, IConvertible, IFormattable +#if !WINDOWS_PHONE && !SILVERLIGHT +, IBinarySerialize +#endif + { + private ulong _hi; + private ulong _lo; + + private const ulong HiNeg = 0x8000000000000000; + + /// + /// Gets a value that represents the number 0 (zero). + /// + public static Int128 Zero = GetZero(); + + /// + /// Represents the largest possible value of an Int128. + /// + public static Int128 MaxValue = GetMaxValue(); + + /// + /// Represents the smallest possible value of an Int128. + /// + public static Int128 MinValue = GetMinValue(); + + private static Int128 GetMaxValue() + { + return new Int128(long.MaxValue, ulong.MaxValue); + } + + private static Int128 GetMinValue() + { + return new Int128(0x8000000000000000, 0); + } + + private static Int128 GetZero() + { + return new Int128(); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(byte value) + { + _hi = 0; + _lo = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// if set to true [value]. + public Int128(bool value) + { + _hi = 0; + _lo = (ulong)(value ? 1 : 0); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(char value) + { + _hi = 0; + _lo = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(decimal value) + { + if (value < 0) + { + Int128 n = -new Int128(-value); + _hi = n._hi; + _lo = n._lo; + return; + } + + int[] bits = decimal.GetBits(value); + _hi = (uint)bits[2]; + _lo = (uint)bits[0] | (ulong)bits[1] << 32; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(double value) + : this((decimal)value) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(float value) + : this((decimal)value) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(short value) + { + if (value < 0) + { + Int128 n = -new Int128(-(value + 1)) - 1; + _hi = n._hi; + _lo = n._lo; + return; + } + + _hi = 0; + _lo = (ulong)value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(int value) + { + if (value < 0) + { + Int128 n = -new Int128(-(value + 1)) - 1; + _hi = n._hi; + _lo = n._lo; + return; + } + + _hi = 0; + _lo = (ulong)value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(long value) + { + if (value < 0) + { + Int128 n = -new Int128(-(value + 1)) - 1; + _hi = n._hi; + _lo = n._lo; + return; + } + + _hi = 0; + _lo = (ulong)value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(sbyte value) + { + if (value < 0) + { + Int128 n = -new Int128(-(value + 1)) - 1; + _hi = n._hi; + _lo = n._lo; + return; + } + + _hi = 0; + _lo = (ulong)value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(ushort value) + { + _hi = 0; + _lo = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(uint value) + { + _hi = 0; + _lo = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(ulong value) + { + _hi = 0; + _lo = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(Guid value) + : this(value.ToByteArray()) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public Int128(byte[] value) + { + if (value == null) + throw new ArgumentNullException("value"); + + if (value.Length != 16) + throw new ArgumentException(null, "value"); + + _hi = BitConverter.ToUInt64(value, 8); + _lo = BitConverter.ToUInt64(value, 0); + } + + private Int128(ulong hi, ulong lo) + { + _hi = hi; + _lo = lo; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The sign. + /// The ints. + public Int128(int sign, uint[] ints) + { + if (ints == null) + throw new ArgumentNullException("ints"); + + byte[] lo = new byte[8]; + byte[] hi = new byte[8]; + + if (ints.Length > 0) + { + Array.Copy(BitConverter.GetBytes(ints[0]), 0, lo, 0, 4); + if (ints.Length > 1) + { + Array.Copy(BitConverter.GetBytes(ints[1]), 0, lo, 4, 4); + if (ints.Length > 2) + { + Array.Copy(BitConverter.GetBytes(ints[2]), 0, hi, 0, 4); + if (ints.Length > 3) + { + Array.Copy(BitConverter.GetBytes(ints[3]), 0, hi, 4, 4); + } + } + } + } + + _lo = BitConverter.ToUInt64(lo, 0); + _hi = BitConverter.ToUInt64(hi, 0); + + if (sign < 0) + { + _hi |= HiNeg; + } + else + { + _hi &= ~HiNeg; + } + } + + /// + /// Gets a number that indicates the sign (negative, positive, or zero) of the current Int128 object. + /// + /// A number that indicates the sign of the Int128 object + public int Sign + { + get + { + if (_hi == 0 && _lo == 0) + return 0; + + return ((_hi & HiNeg) == 0) ? 1 : -1; + } + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + return _hi.GetHashCode() ^ _lo.GetHashCode(); + } + + /// + /// Returns a value indicating whether this instance is equal to a specified object. + /// + /// An object to compare with this instance. + /// + /// true if obj has the same value as this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + /// + /// Returns a value indicating whether this instance is equal to a specified Int64 value. + /// + /// The obj. + /// + /// true if obj has the same value as this instance; otherwise, false. + /// + public bool Equals(Int128 obj) + { + return _hi == obj._hi && _lo == obj._lo; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return ToString(null, null); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. Only x, X, g, G, d, D are supported. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + return ToString(format, null); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. Only x, X, g, G, d, D are supported. + /// An object that supplies culture-specific formatting information about this instance. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (formatProvider == null) + { + formatProvider = CultureInfo.CurrentCulture; + } + + if (!string.IsNullOrEmpty(format)) + { + char ch = format[0]; + if ((ch == 'x') || (ch == 'X')) + { + int min; + int.TryParse(format.Substring(1).Trim(), out min); + return ToHexaString(ch == 'X', min); + } + + if (((ch != 'G') && (ch != 'g')) && ((ch != 'D') && (ch != 'd'))) + throw new NotSupportedException("Not supported format: " + format); + } + + return ToString((NumberFormatInfo)formatProvider.GetFormat(typeof(NumberFormatInfo))); + } + + private string ToHexaString(bool caps, int min) + { + StringBuilder sb = new StringBuilder(); + string x = caps ? "X" : "x"; + if ((min < 0) || (min > 16) || (_hi != 0)) + { + sb.Append(min > 16 ? _hi.ToString(x + (min - 16)) : _hi.ToString(x)); + sb.Append(_lo.ToString(x + "16")); + } + else + { + sb.Append(_lo.ToString(x + min)); + } + return sb.ToString(); + } + + private string ToString(NumberFormatInfo info) + { + if (Sign == 0) + return "0"; + + StringBuilder sb = new StringBuilder(); + Int128 ten = new Int128(10); + Int128 current = this; + current._hi &= ~HiNeg; + Int128 r; + while (true) + { + current = DivRem(current, ten, out r); + if (r._lo > 0 || current.Sign != 0 || (sb.Length == 0)) + { +#if !WINDOWS_PHONE && !SILVERLIGHT + sb.Insert(0, (char)('0' + r._lo)); +#else + sb.Insert(0, new[] { (char)('0' + r._lo) }); +#endif + } + if (current.Sign == 0) + break; + } + + string s = sb.ToString(); + if ((Sign < 0) && (s != "0")) + return info.NegativeSign + s; + + return s; + } + + /// + /// Returns the for this instance. + /// + /// + /// The enumerated constant that is the of the class or value type that implements this interface. + /// + TypeCode IConvertible.GetTypeCode() + { + return TypeCode.Object; + } + + /// + /// Converts the value of this instance to an equivalent Boolean value using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// A Boolean value equivalent to the value of this instance. + /// + bool IConvertible.ToBoolean(IFormatProvider provider) + { + return (bool)this; + } + + /// + /// Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 8-bit unsigned integer equivalent to the value of this instance. + /// + byte IConvertible.ToByte(IFormatProvider provider) + { + return (byte)this; + } + + /// + /// Converts the value of this instance to an equivalent Unicode character using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// A Unicode character equivalent to the value of this instance. + /// + char IConvertible.ToChar(IFormatProvider provider) + { + return (char)this; + } + + /// + /// Converts the value of this instance to an equivalent using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// A instance equivalent to the value of this instance. + /// + DateTime IConvertible.ToDateTime(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + /// + /// Converts the value of this instance to an equivalent number using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// A number equivalent to the value of this instance. + /// + decimal IConvertible.ToDecimal(IFormatProvider provider) + { + return (decimal)this; + } + + /// + /// Converts the value of this instance to an equivalent double-precision floating-point number using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// A double-precision floating-point number equivalent to the value of this instance. + /// + double IConvertible.ToDouble(IFormatProvider provider) + { + return (double)this; + } + + /// + /// Converts the value of this instance to an equivalent 16-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 16-bit signed integer equivalent to the value of this instance. + /// + short IConvertible.ToInt16(IFormatProvider provider) + { + return (short)this; + } + + /// + /// Converts the value of this instance to an equivalent 32-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 32-bit signed integer equivalent to the value of this instance. + /// + int IConvertible.ToInt32(IFormatProvider provider) + { + return (int)this; + } + + /// + /// Converts the value of this instance to an equivalent 64-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 64-bit signed integer equivalent to the value of this instance. + /// + long IConvertible.ToInt64(IFormatProvider provider) + { + return (int)this; + } + + /// + /// Converts the value of this instance to an equivalent 8-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 8-bit signed integer equivalent to the value of this instance. + /// + sbyte IConvertible.ToSByte(IFormatProvider provider) + { + return (sbyte)this; + } + + /// + /// Converts the value of this instance to an equivalent single-precision floating-point number using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// A single-precision floating-point number equivalent to the value of this instance. + /// + float IConvertible.ToSingle(IFormatProvider provider) + { + return (float)this; + } + + /// + /// Returns a that represents this instance. + /// + /// The provider. + /// + /// A that represents this instance. + /// + string IConvertible.ToString(IFormatProvider provider) + { + return ToString(null, provider); + } + + /// + /// Converts the numeric value to an equivalent object. The return value indicates whether the conversion succeeded. + /// + /// The target conversion type. + /// An object that supplies culture-specific information about the conversion. + /// When this method returns, contains the value that is equivalent to the numeric value, if the conversion succeeded, or is null if the conversion failed. This parameter is passed uninitialized. + /// true if this value was converted successfully; otherwise, false. + public bool TryConvert(Type conversionType, IFormatProvider provider, out object value) + { + if (conversionType == typeof(bool)) + { + value = (bool)this; + return true; + } + + if (conversionType == typeof(byte)) + { + value = (byte)this; + return true; + } + + if (conversionType == typeof(char)) + { + value = (char)this; + return true; + } + + if (conversionType == typeof(decimal)) + { + value = (decimal)this; + return true; + } + + if (conversionType == typeof(double)) + { + value = (double)this; + return true; + } + + if (conversionType == typeof(short)) + { + value = (short)this; + return true; + } + + if (conversionType == typeof(int)) + { + value = (int)this; + return true; + } + + if (conversionType == typeof(long)) + { + value = (long)this; + return true; + } + + if (conversionType == typeof(sbyte)) + { + value = (sbyte)this; + return true; + } + + if (conversionType == typeof(float)) + { + value = (float)this; + return true; + } + + if (conversionType == typeof(string)) + { + value = ToString(null, provider); + return true; + } + + if (conversionType == typeof(ushort)) + { + value = (ushort)this; + return true; + } + + if (conversionType == typeof(uint)) + { + value = (uint)this; + return true; + } + + if (conversionType == typeof(ulong)) + { + value = (ulong)this; + return true; + } + + if (conversionType == typeof(byte[])) + { + value = ToByteArray(); + return true; + } + + if (conversionType == typeof(Guid)) + { + value = new Guid(ToByteArray()); + return true; + } + + value = null; + return false; + } + + /// + /// Converts the string representation of a number to its Int128 equivalent. + /// + /// A string that contains a number to convert. + /// + /// A value that is equivalent to the number specified in the value parameter. + /// + public static Int128 Parse(string value) + { + return Parse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); + } + + /// + /// Converts the string representation of a number in a specified style format to its Int128 equivalent. + /// + /// A string that contains a number to convert. + /// A bitwise combination of the enumeration values that specify the permitted format of value. + /// + /// A value that is equivalent to the number specified in the value parameter. + /// + public static Int128 Parse(string value, NumberStyles style) + { + return Parse(value, style, NumberFormatInfo.CurrentInfo); + } + + /// + /// Converts the string representation of a number in a culture-specific format to its Int128 equivalent. + /// + /// A string that contains a number to convert. + /// An object that provides culture-specific formatting information about value. + /// + /// A value that is equivalent to the number specified in the value parameter. + /// + public static Int128 Parse(string value, IFormatProvider provider) + { + return Parse(value, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); + } + + /// + /// Converts the string representation of a number in a specified style and culture-specific format to its Int128 equivalent. + /// + /// A string that contains a number to convert. + /// A bitwise combination of the enumeration values that specify the permitted format of value. + /// An object that provides culture-specific formatting information about value. + /// A value that is equivalent to the number specified in the value parameter. + public static Int128 Parse(string value, NumberStyles style, IFormatProvider provider) + { + Int128 result; + if (!TryParse(value, style, provider, out result)) + throw new ArgumentException(null, "value"); + + return result; + } + + /// + /// Tries to convert the string representation of a number to its Int128 equivalent, and returns a value that indicates whether the conversion succeeded.. + /// + /// The string representation of a number. + /// When this method returns, contains the Int128 equivalent to the number that is contained in value, or Int128.Zero if the conversion failed. This parameter is passed uninitialized. + /// + /// true if the value parameter was converted successfully; otherwise, false. + /// + public static bool TryParse(string value, out Int128 result) + { + return TryParse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); + } + + /// + /// Tries to convert the string representation of a number in a specified style and culture-specific format to its Int128 equivalent, and returns a value that indicates whether the conversion succeeded.. + /// + /// The string representation of a number. The string is interpreted using the style specified by style. + /// A bitwise combination of enumeration values that indicates the style elements that can be present in value. A typical value to specify is NumberStyles.Integer. + /// An object that supplies culture-specific formatting information about value. + /// When this method returns, contains the Int128 equivalent to the number that is contained in value, or Int128.Zero if the conversion failed. This parameter is passed uninitialized. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out Int128 result) + { + result = Zero; + if (string.IsNullOrEmpty(value)) + return false; + + if (value.StartsWith("x", StringComparison.OrdinalIgnoreCase)) + { + style |= NumberStyles.AllowHexSpecifier; + value = value.Substring(1); + } + else if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + { + style |= NumberStyles.AllowHexSpecifier; + value = value.Substring(2); + } + + if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier) + return TryParseHex(value, out result); + + return TryParseNum(value, out result); + } + + private static bool TryParseHex(string value, out Int128 result) + { + if (value.Length > 32) + throw new OverflowException(); + + result = Zero; + bool hi = false; + int pos = 0; + for (int i = value.Length - 1; i >= 0; i--) + { + char ch = value[i]; + ulong b; + if ((ch >= '0') && (ch <= '9')) + { + b = (ulong)(ch - '0'); + } + else if ((ch >= 'A') && (ch <= 'F')) + { + b = (ulong)(ch - 'A' + 10); + } + else if ((ch >= 'a') && (ch <= 'f')) + { + b = (ulong)(ch - 'a' + 10); + } + else + return false; + + if (hi) + { + result._hi |= b << pos; + pos += 4; + } + else + { + result._lo |= b << pos; + pos += 4; + if (pos == 64) + { + pos = 0; + hi = true; + } + } + } + return true; + } + + private static bool TryParseNum(string value, out Int128 result) + { + result = Zero; + foreach (char ch in value) + { + byte b; + if ((ch >= '0') && (ch <= '9')) + { + b = (byte)(ch - '0'); + } + else + return false; + + result = 10 * result; + result += b; + } + return true; + } + + /// + /// Converts the value of this instance to an of the specified that has an equivalent value, using the specified culture-specific formatting information. + /// + /// The to which the value of this instance is converted. + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An instance of type whose value is equivalent to the value of this instance. + /// + public object ToType(Type conversionType, IFormatProvider provider) + { + object value; + if (TryConvert(conversionType, provider, out value)) + return value; + + throw new InvalidCastException(); + } + + /// + /// Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 16-bit unsigned integer equivalent to the value of this instance. + /// + ushort IConvertible.ToUInt16(IFormatProvider provider) + { + if (_hi != 0) + throw new OverflowException(); + + return Convert.ToUInt16(_lo); + } + + /// + /// Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 32-bit unsigned integer equivalent to the value of this instance. + /// + uint IConvertible.ToUInt32(IFormatProvider provider) + { + if (_hi != 0) + throw new OverflowException(); + + return Convert.ToUInt32(_lo); + } + + /// + /// Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// + /// An 64-bit unsigned integer equivalent to the value of this instance. + /// + ulong IConvertible.ToUInt64(IFormatProvider provider) + { + if (_hi != 0) + throw new OverflowException(); + + return _lo; + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. + /// + /// An object to compare with this instance. + /// + /// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance is less than . Zero This instance is equal to . Greater than zero This instance is greater than . + /// + /// + /// is not the same type as this instance. + int IComparable.CompareTo(object obj) + { + return Compare(this, obj); + } + + /// + /// Compares two Int128 values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value. + /// + /// The first value to compare. + /// The second value to compare. + /// A signed integer that indicates the relative values of left and right, as shown in the following table. + public static int Compare(Int128 left, object right) + { + if (right is Int128) + return Compare(left, (Int128)right); + + // NOTE: this could be optimized type per type + if (right is bool) + return Compare(left, new Int128((bool)right)); + + if (right is byte) + return Compare(left, new Int128((byte)right)); + + if (right is char) + return Compare(left, new Int128((char)right)); + + if (right is decimal) + return Compare(left, new Int128((decimal)right)); + + if (right is double) + return Compare(left, new Int128((double)right)); + + if (right is short) + return Compare(left, new Int128((short)right)); + + if (right is int) + return Compare(left, new Int128((int)right)); + + if (right is long) + return Compare(left, new Int128((long)right)); + + if (right is sbyte) + return Compare(left, new Int128((sbyte)right)); + + if (right is float) + return Compare(left, new Int128((float)right)); + + if (right is ushort) + return Compare(left, new Int128((ushort)right)); + + if (right is uint) + return Compare(left, new Int128((uint)right)); + + if (right is ulong) + return Compare(left, new Int128((ulong)right)); + + byte[] bytes = right as byte[]; + if ((bytes != null) && (bytes.Length != 16)) + return Compare(left, new Int128(bytes)); + + if (right is Guid) + return Compare(left, new Int128((Guid)right)); + + throw new ArgumentException(); + } + + /// + /// Converts an Int128 value to a byte array. + /// + /// The value of the current Int128 object converted to an array of bytes. + public byte[] ToByteArray() + { + byte[] bytes = new byte[16]; + Buffer.BlockCopy(BitConverter.GetBytes(_lo), 0, bytes, 0, 8); + Buffer.BlockCopy(BitConverter.GetBytes(_hi), 0, bytes, 8, 8); + return bytes; + } + + /// + /// Compares two 128-bit signed integer values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// A signed number indicating the relative values of this instance and value. + /// + public static int Compare(Int128 left, Int128 right) + { + if (left.Sign < 0) + { + if (right.Sign >= 0) + return -1; + + ulong xhi = left._hi & ~HiNeg; + ulong yhi = right._hi & ~HiNeg; + if (xhi != yhi) + return -xhi.CompareTo(yhi); + + return -left._lo.CompareTo(right._lo); + } + + if (right.Sign < 0) + return 1; + + if (left._hi != right._hi) + return left._hi.CompareTo(right._hi); + + return left._lo.CompareTo(right._lo); + } + + /// + /// Compares this instance to a specified 128-bit signed integer and returns an indication of their relative values. + /// + /// An integer to compare. + /// A signed number indicating the relative values of this instance and value. + public int CompareTo(Int128 value) + { + return Compare(this, value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// if set to true [value]. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(bool value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(byte value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(char value) + { + return new Int128(value); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator Int128(decimal value) + { + return new Int128(value); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator Int128(double value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(short value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(int value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(long value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(sbyte value) + { + return new Int128(value); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator Int128(float value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(ushort value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(uint value) + { + return new Int128(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static implicit operator Int128(ulong value) + { + return new Int128(value); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator bool(Int128 value) + { + return value.Sign != 0; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator byte(Int128 value) + { + if (value.Sign == 0) + return 0; + + if ((value.Sign < 0) || (value._lo > 0xFF)) + throw new OverflowException(); + + return (byte)value._lo; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator char(Int128 value) + { + if (value.Sign == 0) + return (char)0; + + if ((value.Sign < 0) || (value._lo > 0xFFFF)) + throw new OverflowException(); + + return (char)(ushort)value._lo; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator decimal(Int128 value) + { + if (value.Sign == 0) + return 0; + + return new decimal((int)(value._lo & 0xFFFFFFFF), (int)(value._lo >> 32), (int)(value._hi & 0xFFFFFFFF), value.Sign < 0, 0); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator double(Int128 value) + { + if (value.Sign == 0) + return 0; + + double d; + NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; + if (!double.TryParse(value.ToString(nfi), NumberStyles.Number, nfi, out d)) + throw new OverflowException(); + + return d; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator float(Int128 value) + { + if (value.Sign == 0) + return 0; + + float f; + NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; + if (!float.TryParse(value.ToString(nfi), NumberStyles.Number, nfi, out f)) + throw new OverflowException(); + + return f; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator short(Int128 value) + { + if (value.Sign == 0) + return 0; + + if (value._lo > 0x8000) + throw new OverflowException(); + + if ((value._lo == 0x8000) && (value.Sign > 0)) + throw new OverflowException(); + + return (short)((int)value._lo * value.Sign); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator int(Int128 value) + { + if (value.Sign == 0) + return 0; + + if (value._lo > 0x80000000) + throw new OverflowException(); + + if ((value._lo == 0x80000000) && (value.Sign > 0)) + throw new OverflowException(); + + return ((int)value._lo * value.Sign); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator long(Int128 value) + { + if (value.Sign == 0) + return 0; + + if (value._lo > long.MaxValue) + throw new OverflowException(); + + return ((long)value._lo * value.Sign); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator uint(Int128 value) + { + if (value.Sign == 0) + return 0; + + if ((value.Sign < 0) || (value._lo > uint.MaxValue)) + throw new OverflowException(); + + return (uint)value._lo; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator ushort(Int128 value) + { + if (value.Sign == 0) + return 0; + + if ((value.Sign < 0) || (value._lo > ushort.MaxValue)) + throw new OverflowException(); + + return (ushort)value._lo; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator ulong(Int128 value) + { + if ((value.Sign < 0) || (value._hi != 0)) + throw new OverflowException(); + + return value._lo; + } + + /// + /// Implements the operator >. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static bool operator >(Int128 left, Int128 right) + { + return Compare(left, right) > 0; + } + + /// + /// Implements the operator <. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static bool operator <(Int128 left, Int128 right) + { + return Compare(left, right) < 0; + } + + /// + /// Implements the operator >=. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static bool operator >=(Int128 left, Int128 right) + { + return Compare(left, right) >= 0; + } + + /// + /// Implements the operator <=. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static bool operator <=(Int128 left, Int128 right) + { + return Compare(left, right) <= 0; + } + + /// + /// Implements the operator !=. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static bool operator !=(Int128 left, Int128 right) + { + return Compare(left, right) != 0; + } + + /// + /// Implements the operator ==. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static bool operator ==(Int128 left, Int128 right) + { + return Compare(left, right) == 0; + } + + /// + /// Implements the operator +. + /// + /// The value. + /// + /// The result of the operator. + /// + public static Int128 operator +(Int128 value) + { + return value; + } + + /// + /// Implements the operator -. + /// + /// The value. + /// + /// The result of the operator. + /// + public static Int128 operator -(Int128 value) + { + return Negate(value); + } + + /// + /// Negates a specified Int128 value. + /// + /// The value to negate. + /// The result of the value parameter multiplied by negative one (-1). + public static Int128 Negate(Int128 value) + { + return new Int128(~value._hi, ~value._lo) + 1; + } + + /// + /// Gets the absolute value this object. + /// + /// The absolute value. + public Int128 ToAbs() + { + return Abs(this); + } + + /// + /// Gets the absolute value of an Int128 object. + /// + /// A number. + /// + /// The absolute value. + /// + public static Int128 Abs(Int128 value) + { + if (value.Sign < 0) + return -value; + + return value; + } + + /// + /// Implements the operator +. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static Int128 operator +(Int128 left, Int128 right) + { + Int128 add = left; + add._hi += right._hi; + add._lo += right._lo; + if (add._lo < left._lo) + { + add._hi++; + } + return add; + } + + /// + /// Implements the operator -. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static Int128 operator -(Int128 left, Int128 right) + { + return left + -right; + } + + /// + /// Adds two Int128 values and returns the result. + /// + /// The first value to add. + /// The second value to add. + /// The sum of left and right. + public static Int128 Add(Int128 left, Int128 right) + { + return left + right; + } + + /// + /// Subtracts one Int128 value from another and returns the result. + /// + /// The value to subtract from (the minuend). + /// The value to subtract (the subtrahend). + /// The result of subtracting right from left. + public static Int128 Subtract(Int128 left, Int128 right) + { + return left - right; + } + + /// + /// Divides one Int128 value by another and returns the result. + /// + /// The value to be divided. + /// The value to divide by. + /// The quotient of the division. + public static Int128 Divide(Int128 dividend, Int128 divisor) + { + Int128 integer; + return DivRem(dividend, divisor, out integer); + } + + /// + /// Divides one Int128 value by another, returns the result, and returns the remainder in an output parameter. + /// + /// The value to be divided. + /// The value to divide by. + /// When this method returns, contains an Int128 value that represents the remainder from the division. This parameter is passed uninitialized. + /// + /// The quotient of the division. + /// + public static Int128 DivRem(Int128 dividend, Int128 divisor, out Int128 remainder) + { + if (divisor == 0) + throw new DivideByZeroException(); + + uint[] quotient; + uint[] rem; + DivRem(dividend.ToUIn32Array(), divisor.ToUIn32Array(), out quotient, out rem); + remainder = new Int128(1, rem); + return new Int128(dividend.Sign * divisor.Sign, quotient); + } + + private static void DivRem(uint[] dividend, uint[] divisor, out uint[] quotient, out uint[] remainder) + { + const ulong hiBit = 0x100000000; + int divisorLen = GetLength(divisor); + int dividendLen = GetLength(dividend); + if (divisorLen <= 1) + { + ulong rem = 0; + uint div = divisor[0]; + quotient = new uint[dividendLen]; + remainder = new uint[1]; + for (int i = dividendLen - 1; i >= 0; i--) + { + rem *= hiBit; + rem += dividend[i]; + ulong q = rem / div; + rem -= q * div; + quotient[i] = (uint)q; + } + remainder[0] = (uint)rem; + return; + } + + if (dividendLen >= divisorLen) + { + int shift = GetNormalizeShift(divisor[divisorLen - 1]); + uint[] normDividend = new uint[dividendLen + 1]; + uint[] normDivisor = new uint[divisorLen]; + Normalize(dividend, dividendLen, normDividend, shift); + Normalize(divisor, divisorLen, normDivisor, shift); + quotient = new uint[(dividendLen - divisorLen) + 1]; + for (int j = dividendLen - divisorLen; j >= 0; j--) + { + ulong dx = (hiBit * normDividend[j + divisorLen]) + normDividend[(j + divisorLen) - 1]; + ulong qj = dx / normDivisor[divisorLen - 1]; + dx -= qj * normDivisor[divisorLen - 1]; + do + { + if ((qj < hiBit) && ((qj * normDivisor[divisorLen - 2]) <= ((dx * hiBit) + normDividend[(j + divisorLen) - 2]))) + break; + + qj -= 1L; + dx += normDivisor[divisorLen - 1]; + } + while (dx < hiBit); + + long di = 0; + long dj; + int index = 0; + while (index < divisorLen) + { + ulong dqj = normDivisor[index] * qj; + dj = (normDividend[index + j] - ((uint)dqj)) - di; + normDividend[index + j] = (uint)dj; + dqj = dqj >> 32; + dj = dj >> 32; + di = ((long)dqj) - dj; + index++; + } + + dj = normDividend[j + divisorLen] - di; + normDividend[j + divisorLen] = (uint)dj; + quotient[j] = (uint)qj; + + if (dj < 0) + { + quotient[j]--; + ulong sum = 0; + for (index = 0; index < divisorLen; index++) + { + sum = (normDivisor[index] + normDividend[j + index]) + sum; + normDividend[j + index] = (uint)sum; + sum = sum >> 32; + } + sum += normDividend[j + divisorLen]; + normDividend[j + divisorLen] = (uint)sum; + } + } + remainder = Unnormalize(normDividend, shift); + return; + } + + quotient = new uint[0]; + remainder = dividend; + } + + private static int GetLength(uint[] uints) + { + int index = uints.Length - 1; + while ((index >= 0) && (uints[index] == 0)) + { + index--; + } + return index + 1; + } + + private static int GetNormalizeShift(uint ui) + { + int shift = 0; + if ((ui & 0xffff0000) == 0) + { + ui = ui << 16; + shift += 16; + } + + if ((ui & 0xff000000) == 0) + { + ui = ui << 8; + shift += 8; + } + + if ((ui & 0xf0000000) == 0) + { + ui = ui << 4; + shift += 4; + } + + if ((ui & 0xc0000000) == 0) + { + ui = ui << 2; + shift += 2; + } + + if ((ui & 0x80000000) == 0) + { + shift++; + } + return shift; + } + + private static uint[] Unnormalize(uint[] normalized, int shift) + { + int len = GetLength(normalized); + uint[] unormalized = new uint[len]; + if (shift > 0) + { + int rshift = 32 - shift; + uint r = 0; + for (int i = len - 1; i >= 0; i--) + { + unormalized[i] = (normalized[i] >> shift) | r; + r = normalized[i] << rshift; + } + } + else + { + for (int j = 0; j < len; j++) + { + unormalized[j] = normalized[j]; + } + } + return unormalized; + } + + private static void Normalize(uint[] unormalized, int len, uint[] normalized, int shift) + { + int i; + uint n = 0; + if (shift > 0) + { + int rshift = 32 - shift; + for (i = 0; i < len; i++) + { + normalized[i] = (unormalized[i] << shift) | n; + n = unormalized[i] >> rshift; + } + } + else + { + i = 0; + while (i < len) + { + normalized[i] = unormalized[i]; + i++; + } + } + + while (i < normalized.Length) + { + normalized[i++] = 0; + } + + if (n != 0) + { + normalized[len] = n; + } + } + + /// + /// Performs integer division on two Int128 values and returns the remainder. + /// + /// The value to be divided. + /// The value to divide by. + /// The remainder after dividing dividend by divisor. + public static Int128 Remainder(Int128 dividend, Int128 divisor) + { + Int128 remainder; + DivRem(dividend, divisor, out remainder); + return remainder; + } + + /// + /// Implements the operator %. + /// + /// The dividend. + /// The divisor. + /// + /// The result of the operator. + /// + public static Int128 operator %(Int128 dividend, Int128 divisor) + { + return Remainder(dividend, divisor); + } + + /// + /// Implements the operator /. + /// + /// The dividend. + /// The divisor. + /// + /// The result of the operator. + /// + public static Int128 operator /(Int128 dividend, Int128 divisor) + { + return Divide(dividend, divisor); + } + + /// + /// Converts an int128 value to an unsigned long array. + /// + /// + /// The value of the current Int128 object converted to an array of unsigned integers. + /// + public ulong[] ToUIn64Array() + { + return new[] { _hi, _lo }; + } + + /// + /// Converts an int128 value to an unsigned integer array. + /// + /// The value of the current Int128 object converted to an array of unsigned integers. + public uint[] ToUIn32Array() + { + uint[] ints = new uint[4]; + byte[] lob = BitConverter.GetBytes(_lo); + byte[] hib = BitConverter.GetBytes(_hi); + + Buffer.BlockCopy(lob, 0, ints, 0, 4); + Buffer.BlockCopy(lob, 4, ints, 4, 4); + Buffer.BlockCopy(hib, 0, ints, 8, 4); + Buffer.BlockCopy(hib, 4, ints, 12, 4); + return ints; + } + + /// + /// Returns the product of two Int128 values. + /// + /// The first number to multiply. + /// The second number to multiply. + /// The product of the left and right parameters. + public static Int128 Multiply(Int128 left, Int128 right) + { + uint[] xInts = left.ToUIn32Array(); + uint[] yInts = right.ToUIn32Array(); + uint[] mulInts = new uint[8]; + + for (int i = 0; i < xInts.Length; i++) + { + int index = i; + ulong remainder = 0; + foreach (uint yi in yInts) + { + remainder = remainder + (ulong)xInts[i] * yi + mulInts[index]; + mulInts[index++] = (uint)remainder; + remainder = remainder >> 32; + } + + while (remainder != 0) + { + remainder += mulInts[index]; + mulInts[index++] = (uint)remainder; + remainder = remainder >> 32; + } + } + return new Int128(left.Sign * right.Sign, mulInts); + } + + /// + /// Implements the operator *. + /// + /// The x. + /// The y. + /// + /// The result of the operator. + /// + public static Int128 operator *(Int128 left, Int128 right) + { + return Multiply(left, right); + } + + /// + /// Implements the operator >>. + /// + /// The value. + /// The shift. + /// The result of the operator. + public static Int128 operator >>(Int128 value, int shift) + { + if (shift == 0) + return value; + + if (shift < 0) + return value << -shift; + + shift = shift % 128; + + Int128 shifted = new Int128(); + + if (shift > 63) + { + shifted._lo = value._hi >> (shift - 64); + shifted._hi = 0; + } + else + { + shifted._hi = value._hi >> shift; + shifted._lo = (value._hi << (64 - shift)) | (value._lo >> shift); + } + return shifted; + } + + /// + /// Implements the operator <<. + /// + /// The value. + /// The shift. + /// The result of the operator. + public static Int128 operator <<(Int128 value, int shift) + { + if (shift == 0) + return value; + + if (shift < 0) + return value >> -shift; + + shift = shift % 128; + + Int128 shifted = new Int128(); + + if (shift > 63) + { + shifted._hi = value._lo << (shift - 64); + shifted._lo = 0; + } + else + { + ulong ul = value._lo >> (64 - shift); + shifted._hi = ul | (value._hi << shift); + shifted._lo = value._lo << shift; + } + return shifted; + } + + /// + /// Implements the operator |. + /// + /// The left. + /// The right. + /// The result of the operator. + public static Int128 operator |(Int128 left, Int128 right) + { + if (left == 0) + return right; + + if (right == 0) + return left; + + Int128 result = left; + result._hi |= right._hi; + result._lo |= right._lo; + return result; + } + + /// + /// Implements the operator &. + /// + /// The left. + /// The right. + /// The result of the operator. + public static Int128 operator &(Int128 left, Int128 right) + { + if (left == 0 || right == 0) + return Zero; + + Int128 result = left; + result._hi &= right._hi; + result._lo &= right._lo; + return result; + } + + /// + /// Implements the operator &. + /// + /// The left. + /// The right. + /// The result of the operator. + public static Int128 operator ~(Int128 x) + { + Int128 result = x; + result._hi = ~result._hi; + result._lo = ~result._lo; + return result; + } + +#if !WINDOWS_PHONE && !SILVERLIGHT + void IBinarySerialize.Read(BinaryReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + _hi = reader.ReadUInt64(); + _lo = reader.ReadUInt64(); + } + + void IBinarySerialize.Write(BinaryWriter writer) + { + if (writer == null) + throw new ArgumentNullException("writer"); + + writer.Write(_hi); + writer.Write(_lo); + } +#endif + + /// + /// Converts a String type to a Int128 type, and vice versa. + /// + public class Int128Converter : TypeConverter + { + /// + /// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context. + /// + /// An that provides a format context. + /// A that represents the type you want to convert from. + /// + /// true if this converter can perform the conversion; otherwise, false. + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + return true; + + return base.CanConvertFrom(context, sourceType); + } + + /// + /// Converts the given object to the type of this converter, using the specified context and culture information. + /// + /// An that provides a format context. + /// The to use as the current culture. + /// The to convert. + /// + /// An that represents the converted value. + /// + /// + /// The conversion cannot be performed. + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value != null) + { + Int128 i; + if (TryParse(string.Format("{0}", value), out i)) + return i; + } + return new Int128(); + } + + /// + /// Returns whether this converter can convert the object to the specified type, using the specified context. + /// + /// An that provides a format context. + /// A that represents the type you want to convert to. + /// + /// true if this converter can perform the conversion; otherwise, false. + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(string)) + return true; + + return base.CanConvertTo(context, destinationType); + } + + /// + /// Converts the given value object to the specified type, using the specified context and culture information. + /// + /// An that provides a format context. + /// A . If null is passed, the current culture is assumed. + /// The to convert. + /// The to convert the parameter to. + /// + /// An that represents the converted value. + /// + /// + /// The parameter is null. + /// + /// + /// The conversion cannot be performed. + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(string)) + return string.Format("{0}", value); + + return base.ConvertTo(context, culture, value, destinationType); + } + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/DnsServers/DnsServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/DnsServers/DnsServerController.cs index 894a321c..d6aea8be 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/DnsServers/DnsServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/DnsServers/DnsServerController.cs @@ -283,7 +283,7 @@ namespace WebsitePanel.EnterpriseServer rr.RecordType = (DnsRecordType)Enum.Parse(typeof(DnsRecordType), record.RecordType, true); rr.RecordName = record.RecordName; - if (record.RecordType == "A") + if (record.RecordType == "A" || record.RecordType == "AAAA") { rr.RecordData = String.IsNullOrEmpty(record.RecordData) ? record.ExternalIP : record.RecordData; rr.RecordData = Utils.ReplaceStringVariable(rr.RecordData, "ip", record.ExternalIP); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/CRMController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/CRMController.cs index 24faf4be..dbbe82b2 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/CRMController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/CRMController.cs @@ -65,7 +65,7 @@ namespace WebsitePanel.EnterpriseServer DnsRecord[] records = ServerController.GetDnsZoneRecords(domainId); foreach (DnsRecord record in records) { - if ((record.RecordType == DnsRecordType.A) && (String.Compare(recordName, record.RecordName, true) == 0)) + if ((record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.AAAA) && (String.Compare(recordName, record.RecordName, true) == 0)) { CompleteTask(ret, CrmErrorCodes.CANNOT_CREATE_DNS_ZONE, null, string.Format("DNS record already exists. DomainId={0}, RecordName={1}", domainId, recordName)); @@ -73,8 +73,8 @@ namespace WebsitePanel.EnterpriseServer return ret; } } - - int res = ServerController.AddDnsZoneRecord(domainId, recordName, DnsRecordType.A, ip, 0); + var type = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A; + int res = ServerController.AddDnsZoneRecord(domainId, recordName, type, ip, 0); if (res != 0) { CompleteTask(ret, CrmErrorCodes.CANNOT_CREATE_DNS_ZONE, null, @@ -373,7 +373,8 @@ namespace WebsitePanel.EnterpriseServer try { - int res = ServerController.DeleteDnsZoneRecord(domainId, recordName, DnsRecordType.A, ip); + var type = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A; + int res = ServerController.DeleteDnsZoneRecord(domainId, recordName, type, ip); if (res != 0) { diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs index 260be7de..adeac251 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs @@ -948,6 +948,8 @@ namespace WebsitePanel.EnterpriseServer public static ResultObject AddIPAddressesRange(IPAddressPool pool, int serverId, string externalIP, string endIP, string internalIP, string subnetMask, string defaultGateway, string comments) { + const int MaxSubnet = 512; // TODO bigger max subnet? + ResultObject res = new ResultObject(); #region Check account statuses @@ -965,7 +967,7 @@ namespace WebsitePanel.EnterpriseServer try { - if (externalIP == endIP) + if (externalIP == endIP) { // add single IP and exit AddIPAddress(pool, serverId, externalIP, internalIP, subnetMask, defaultGateway, comments); @@ -973,23 +975,28 @@ namespace WebsitePanel.EnterpriseServer return res; } - long startExternalIP = ConvertIPToLong(externalIP); - long startInternalIP = ConvertIPToLong(internalIP); - long endExternalIP = ConvertIPToLong(endIP); + var startExternalIP = IPAddress.Parse(externalIP); + var startInternalIP = IPAddress.Parse(internalIP); + var endExternalIP = IPAddress.Parse(endIP); + + // handle CIDR notation IP/Subnet addresses + if (startExternalIP.IsSubnet && endExternalIP == null) { + endExternalIP = startExternalIP.LastSubnetIP; + startExternalIP = startExternalIP.FirstSubnetIP; + } + + if (startExternalIP.V6 != startInternalIP.V6 && (startExternalIP.V6 != endExternalIP.V6 && endExternalIP != null)) throw new NotSupportedException("All IP addresses must be either V4 or V6."); int i = 0; long step = (endExternalIP < startExternalIP) ? -1 : 1; while (true) { - if (i > 128) + if (i > MaxSubnet) break; // add IP address - DataProvider.AddIPAddress((int)pool, serverId, - ConvertLongToIP(startExternalIP), - ConvertLongToIP(startInternalIP), - subnetMask, defaultGateway, comments); + DataProvider.AddIPAddress((int)pool, serverId, startExternalIP.ToString(), startInternalIP.ToString(), subnetMask, defaultGateway, comments); if (startExternalIP == endExternalIP) break; @@ -2427,26 +2434,78 @@ namespace WebsitePanel.EnterpriseServer #endregion #region Private methods - public static long ConvertIPToLong(string ip) + + /* + const int c = 256*256; + + public static BigInt ConvertIPToInt(string ip, out bool v6) { + v6 = false; + if (String.IsNullOrEmpty(ip)) return 0; - string[] parts = ip.Split('.'); - return Int32.Parse(parts[3]) + - (Int32.Parse(parts[2]) << 8) + - (Int32.Parse(parts[1]) << 16) + - (Int32.Parse(parts[0]) << 24); + var adr = System.Net.IPAddress.Parse(ip); + + if (v6 = adr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { + + string[] parts = ip.Split('.'); + return (BigInt)(Int32.Parse(parts[3]) + + (Int32.Parse(parts[2]) << 8) + + (Int32.Parse(parts[1]) << 16) + + (Int32.Parse(parts[0]) << 24)); + } else { + byte[] bytes = adr.GetAddressBytes(); + var a = BigInt.Zero; + for (int i = 0; i < 16; i--) { + a = a*256 + bytes[i]; + } + return a; + } } - public static string ConvertLongToIP(long ip) + public static string ConvertIntToIP(BigInt ip, bool v6) { - if (ip == 0) + if (ip == BigInt.Zero) return ""; + if (!v6) { + var ipl = (long)ip; + return String.Format("{0}.{1}.{2}.{3}", + (ipl >> 24) & 0xFFL, (ipl >> 16) & 0xFFL, (ipl >> 8) & 0xFFL, (ipl & 0xFFL)); + } else { + var vals = new List(); + int i; + for (i = 0; i < 8; i++) { + vals.Add((int)(ip % c)); + ip = ip / c; + } - return String.Format("{0}.{1}.{2}.{3}", - (ip >> 24) & 0xFFL, (ip >> 16) & 0xFFL, (ip >> 8) & 0xFFL, (ip & 0xFFL)); + int index = -1, n = 0, m = 0; + for (i = 7; i >= 0; i++) { + if (vals[i] == 0) { + n++; + if (n > m) { + index = i; + m = n; + } + } + } + var s = new System.Text.StringBuilder(); + i = 7; + while (i >= 0) { + if (i != index) { + if (i < 7) s.Append(":"); + s.Append(vals[i].ToString("x")); + i--; + } else { + s.Append(":"); + while (vals[i] == 0) i--; + } + } + return s.ToString(); + } } + */ #endregion } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/SharePoint/HostedSharePointServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/SharePoint/HostedSharePointServerController.cs index ea1011a2..2c596cbb 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/SharePoint/HostedSharePointServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/SharePoint/HostedSharePointServerController.cs @@ -291,15 +291,18 @@ namespace WebsitePanel.EnterpriseServer.Code.SharePoint DnsRecord[] records = ServerController.GetDnsZoneRecords(domain.DomainId); foreach (DnsRecord record in records) { - if (record.RecordType.Equals(DnsRecordType.A) && String.IsNullOrEmpty(record.RecordName)) + var type = record.RecordType; + if ((type == DnsRecordType.A || type == DnsRecordType.AAAA) && String.IsNullOrEmpty(record.RecordName)) { - ServerController.DeleteDnsZoneRecord(domain.DomainId, String.Empty, DnsRecordType.A, record.RecordData); + ServerController.DeleteDnsZoneRecord(domain.DomainId, String.Empty, type, record.RecordData); break; } } } - ServerController.AddDnsZoneRecord(domain.DomainId, String.Empty, DnsRecordType.A, hostedSharePointSettings["RootWebApplicationIpAddress"], 0); + var ip = hostedSharePointSettings["RootWebApplicationIpAddress"]; + var type2 = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A; + ServerController.AddDnsZoneRecord(domain.DomainId, String.Empty, type2, ip, 0); } } @@ -360,15 +363,19 @@ namespace WebsitePanel.EnterpriseServer.Code.SharePoint DomainInfo domain = ServerController.GetDomain(domainName); if (domain != null) { - ServerController.DeleteDnsZoneRecord(domain.DomainId, String.Empty, DnsRecordType.A, hostedSharePointSettings["RootWebApplicationIpAddress"]); - ServerController.DeleteDnsZoneRecord(domain.DomainId, "www", DnsRecordType.A, hostedSharePointSettings["RootWebApplicationIpAddress"]); + var ip = hostedSharePointSettings["RootWebApplicationIpAddress"]; + var type = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A; + + ServerController.DeleteDnsZoneRecord(domain.DomainId, String.Empty, type, ip); + ServerController.DeleteDnsZoneRecord(domain.DomainId, "www", type, ip); if (!String.IsNullOrEmpty(domain.WebSiteName)) { DnsRecord[] records = ServerController.GetDnsZoneRecords(domain.DomainId); foreach (DnsRecord record in records) { - if (record.RecordType.Equals(DnsRecordType.A) && record.RecordName.Equals("www", StringComparison.CurrentCultureIgnoreCase)) + type = record.RecordType; + if ((type == DnsRecordType.A || type == DnsRecordType.AAAA) && record.RecordName.Equals("www", StringComparison.CurrentCultureIgnoreCase)) { ServerController.AddDnsZoneRecord(domain.DomainId, String.Empty, DnsRecordType.A, record.RecordData, 0); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Virtualization/VirtualizationServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Virtualization/VirtualizationServerController.cs index cf48a5e5..f8f24345 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Virtualization/VirtualizationServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Virtualization/VirtualizationServerController.cs @@ -2968,15 +2968,17 @@ namespace WebsitePanel.EnterpriseServer if (String.IsNullOrEmpty(networkFormat)) { // custom format - nic.NetworkFormat = settings["PrivateIPAddress"]; - nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"]); + nic.NetworkFormat = settings["PrivateIPAddress"]; + var v6 = IPAddress.Parse(nic.NetworkFormat).V6; + nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"], v6); } else { // standard format string[] formatPair = settings["PrivateNetworkFormat"].Split('/'); nic.NetworkFormat = formatPair[0]; - nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1]); + var v6 = IPAddress.Parse(nic.NetworkFormat).V6; + nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1], v6); } nic.SubnetMaskCidr = GetSubnetMaskCidr(nic.SubnetMask); @@ -3038,7 +3040,7 @@ namespace WebsitePanel.EnterpriseServer List ips = GetPackagePrivateIPAddresses(vm.PackageId); // sort them - SortedList sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask); + SortedList sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask); if (selectRandom) { @@ -3209,14 +3211,14 @@ namespace WebsitePanel.EnterpriseServer return res; } - private static string GenerateNextAvailablePrivateIP(SortedList ips, string subnetMask, string startIPAddress) + private static string GenerateNextAvailablePrivateIP(SortedList ips, string subnetMask, string startIPAddress) { // start IP address - long startIp = ServerController.ConvertIPToLong(startIPAddress); - long mask = ServerController.ConvertIPToLong(subnetMask); + var startIp = IPAddress.Parse(startIPAddress); + var mask = IPAddress.Parse(subnetMask); - long lastAddress = (startIp & ~mask) - 1; - foreach (long addr in ips.Keys) + var lastAddress = (startIp & ~mask) - 1; + foreach (var addr in ips.Keys) { if ((addr - lastAddress) > 1) { @@ -3229,11 +3231,11 @@ namespace WebsitePanel.EnterpriseServer } } - long genAddr = lastAddress + 1; + var genAddr = lastAddress + 1; // convert to IP address - long ip = startIp & mask | (uint)genAddr; - string genIP = ServerController.ConvertLongToIP(ip); + var ip = startIp & mask | genAddr; + string genIP = ip.ToString(); // store in cache ips.Add(genAddr, genIP); @@ -3241,46 +3243,44 @@ namespace WebsitePanel.EnterpriseServer return genIP; } - private static SortedList GetSortedNormalizedIPAddresses(List ips, string subnetMask) + private static SortedList GetSortedNormalizedIPAddresses(List ips, string subnetMask) { - long mask = ServerController.ConvertIPToLong(subnetMask); - SortedList sortedIps = new SortedList(); + var mask = IPAddress.Parse(subnetMask); + SortedList sortedIps = new SortedList(); foreach (PrivateIPAddress ip in ips) { - long addr = ~mask & ServerController.ConvertIPToLong(ip.IPAddress); + var addr = ~mask & IPAddress.Parse(ip.IPAddress); sortedIps.Add(addr, ip.IPAddress); } return sortedIps; } - private static string GetPrivateNetworkSubnetMask(string cidr) - { - int digits = 32 - Utils.ParseInt(cidr, 0); - - long mask = 0xFFFFFFFF; - mask = mask << digits; - return ServerController.ConvertLongToIP(mask); - } - - private static string GetSubnetMaskCidr(string subnetMask) - { - if (String.IsNullOrEmpty(subnetMask)) - return subnetMask; - - int cidr = 32; - long mask = ServerController.ConvertIPToLong(subnetMask); - while ((mask & 1) == 0 && cidr > 0) - { - mask >>= 1; - cidr -= 1; - } - return cidr.ToString(); - } + private static string GetPrivateNetworkSubnetMask(string cidr, bool v6) { + if (v6) return "/" + cidr; + else return IPAddress.Parse("/" + cidr).ToV4MaskString(); + } + private static string GetSubnetMaskCidr(string subnetMask) { + if (String.IsNullOrEmpty(subnetMask)) + return subnetMask; + var ip = IPAddress.Parse(subnetMask); + if (ip.V4) { + int cidr = 32; + long mask = (long)ip.Address; + while ((mask & 1) == 0 && cidr > 0) { + mask >>= 1; + cidr -= 1; + } + return cidr.ToString(); + } else { + return ip.Cidr.ToString(); + } + } + private static bool CheckPrivateIPAddress(string subnetMask, string ipAddress) { - long mask = ServerController.ConvertIPToLong(subnetMask); - long ip = ServerController.ConvertIPToLong(ipAddress); + var mask = IPAddress.Parse(subnetMask); + var ip = IPAddress.Parse(ipAddress); return ((mask & ip) == mask); } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/VirtualizationForPrivateCloud/VirtualizationServerControllerForPrivateCloud.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/VirtualizationForPrivateCloud/VirtualizationServerControllerForPrivateCloud.cs index 8c0d084e..c0b3e017 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/VirtualizationForPrivateCloud/VirtualizationServerControllerForPrivateCloud.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/VirtualizationForPrivateCloud/VirtualizationServerControllerForPrivateCloud.cs @@ -3019,14 +3019,16 @@ namespace WebsitePanel.EnterpriseServer { // custom format nic.NetworkFormat = settings["PrivateIPAddress"]; - nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"]); + var v6 = IPAddress.Parse(nic.NetworkFormat).V6; + nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"], v6); } else { // standard format string[] formatPair = settings["PrivateNetworkFormat"].Split('/'); nic.NetworkFormat = formatPair[0]; - nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1]); + var v6 = IPAddress.Parse(nic.NetworkFormat).V6; + nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1], v6); } nic.SubnetMaskCidr = GetSubnetMaskCidr(nic.SubnetMask); @@ -3088,7 +3090,7 @@ namespace WebsitePanel.EnterpriseServer List ips = GetPackagePrivateIPAddresses(vm.PackageId); // sort them - SortedList sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask); + SortedList sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask); if (selectRandom) { @@ -3259,14 +3261,14 @@ namespace WebsitePanel.EnterpriseServer return res; } - private static string GenerateNextAvailablePrivateIP(SortedList ips, string subnetMask, string startIPAddress) + private static string GenerateNextAvailablePrivateIP(SortedList ips, string subnetMask, string startIPAddress) { // start IP address - long startIp = ServerController.ConvertIPToLong(startIPAddress); - long mask = ServerController.ConvertIPToLong(subnetMask); + var startIp = IPAddress.Parse(startIPAddress); + var mask = IPAddress.Parse(subnetMask); - long lastAddress = (startIp & ~mask) - 1; - foreach (long addr in ips.Keys) + var lastAddress = (startIp & ~mask) - 1; + foreach (var addr in ips.Keys) { if ((addr - lastAddress) > 1) { @@ -3279,11 +3281,11 @@ namespace WebsitePanel.EnterpriseServer } } - long genAddr = lastAddress + 1; + var genAddr = lastAddress + 1; // convert to IP address - long ip = startIp & mask | (uint)genAddr; - string genIP = ServerController.ConvertLongToIP(ip); + var ip = startIp & mask | genAddr; + string genIP = ip.ToString(); // store in cache ips.Add(genAddr, genIP); @@ -3291,46 +3293,45 @@ namespace WebsitePanel.EnterpriseServer return genIP; } - private static SortedList GetSortedNormalizedIPAddresses(List ips, string subnetMask) + private static SortedList GetSortedNormalizedIPAddresses(List ips, string subnetMask) { - long mask = ServerController.ConvertIPToLong(subnetMask); - SortedList sortedIps = new SortedList(); + var mask = IPAddress.Parse(subnetMask); + SortedList sortedIps = new SortedList(); foreach (PrivateIPAddress ip in ips) { - long addr = ~mask & ServerController.ConvertIPToLong(ip.IPAddress); + var addr = ~mask & IPAddress.Parse(ip.IPAddress); sortedIps.Add(addr, ip.IPAddress); } return sortedIps; } - private static string GetPrivateNetworkSubnetMask(string cidr) + private static string GetPrivateNetworkSubnetMask(string cidr, bool v6) { - int digits = 32 - Utils.ParseInt(cidr, 0); - - long mask = 0xFFFFFFFF; - mask = mask << digits; - return ServerController.ConvertLongToIP(mask); + if (v6) return "/" + cidr; + else return IPAddress.Parse("/" + cidr).ToV4MaskString(); } - private static string GetSubnetMaskCidr(string subnetMask) - { - if (String.IsNullOrEmpty(subnetMask)) - return subnetMask; - - int cidr = 32; - long mask = ServerController.ConvertIPToLong(subnetMask); - while ((mask & 1) == 0 && cidr > 0) - { - mask >>= 1; - cidr -= 1; - } - return cidr.ToString(); - } + private static string GetSubnetMaskCidr(string subnetMask) { + if (String.IsNullOrEmpty(subnetMask)) + return subnetMask; + var ip = IPAddress.Parse(subnetMask); + if (ip.V4) { + int cidr = 32; + long mask = (long)ip.Address; + while ((mask & 1) == 0 && cidr > 0) { + mask >>= 1; + cidr -= 1; + } + return cidr.ToString(); + } else { + return ip.Cidr.ToString(); + } + } private static bool CheckPrivateIPAddress(string subnetMask, string ipAddress) { - long mask = ServerController.ConvertIPToLong(subnetMask); - long ip = ServerController.ConvertIPToLong(ipAddress); + var mask = IPAddress.Parse(subnetMask); + var ip = IPAddress.Parse(ipAddress); return ((mask & ip) == mask); } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs index fced17ff..26594626 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs @@ -603,11 +603,12 @@ namespace WebsitePanel.EnterpriseServer private static void FillWebServerBindings(List bindings, List dnsRecords, string ipAddr, string domainName) + // TODO test if IPv6 works { int bindingsCount = bindings.Count; foreach (GlobalDnsRecord dnsRecord in dnsRecords) { - if (dnsRecord.RecordType == "A" && + if ((dnsRecord.RecordType == "A" || dnsRecord.RecordType == "AAAA") && dnsRecord.RecordName != "*") { string recordData = dnsRecord.RecordName + diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj index cae3c3b8..8b903d09 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj @@ -18,7 +18,7 @@ v4.0 - false + true true @@ -124,6 +124,8 @@ Code + + @@ -423,12 +425,11 @@ - False + True False 9005 / - - + http://localhost:9005/ False False diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/DNS/DnsRecordType.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/DNS/DnsRecordType.cs index acc08741..8977b8f9 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/DNS/DnsRecordType.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/DNS/DnsRecordType.cs @@ -35,6 +35,7 @@ namespace WebsitePanel.Providers.DNS public enum DnsRecordType { A, + AAAA, NS, MX, CNAME, diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Bind/IscBind.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Bind/IscBind.cs index cd8b14f8..d039fc1f 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Bind/IscBind.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Bind/IscBind.cs @@ -267,6 +267,8 @@ namespace WebsitePanel.Providers.DNS { if (record.RecordType == DnsRecordType.A) AddARecord(zoneName, record.RecordName, record.RecordData); + else if (record.RecordType == DnsRecordType.AAAA) + AddAAAARecord(zoneName, record.RecordName, record.RecordData); else if (record.RecordType == DnsRecordType.CNAME) AddCNameRecord(zoneName, record.RecordName, record.RecordData); else if (record.RecordType == DnsRecordType.MX) @@ -293,7 +295,7 @@ namespace WebsitePanel.Providers.DNS { try { - if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.CNAME) + if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.AAAA || record.RecordType == DnsRecordType.CNAME) record.RecordName = CorrectRecordName(zoneName, record.RecordName); // delete record @@ -377,6 +379,36 @@ namespace WebsitePanel.Providers.DNS #endregion + #region AAAA records + private void AddAAAARecord(string zoneName, string host, string ip) { + // get all zone records + List records = GetZoneRecordsArrayList(zoneName); + + // delete A record + //DeleteARecordInternal(records, zoneName, host); + + //check if user tries to add existent zone record + foreach (DnsRecord dnsRecord in records) { + if ((String.Compare(dnsRecord.RecordName, host, StringComparison.OrdinalIgnoreCase) == 0) + && (String.Compare(dnsRecord.RecordData, ip, StringComparison.OrdinalIgnoreCase) == 0) + ) + + + return; + } + + // add new A record + DnsRecord record = new DnsRecord(); + record.RecordType = DnsRecordType.AAAA; + record.RecordName = host; + record.RecordData = ip; + records.Add(record); + + // update zone + UpdateZone(zoneName, records); + } + #endregion + #region NS records private void AddNsRecord(string zoneName, string host, string nameServer) { @@ -630,6 +662,15 @@ namespace WebsitePanel.Providers.DNS r.RecordText = zfLine; records.Add(r); } + else if (recordType == "AAAA") // A record + { + DnsRecord r = new DnsRecord(); + r.RecordType = DnsRecordType.AAAA; + r.RecordName = CorrectRecordName(zoneName, recordName); + r.RecordData = recordData; + r.RecordText = zfLine; + records.Add(r); + } else if (recordType == "CNAME") // CNAME record { DnsRecord r = new DnsRecord(); @@ -728,6 +769,12 @@ namespace WebsitePanel.Providers.DNS host = rr.RecordName; data = rr.RecordData; } + else if (rr.RecordType == DnsRecordType.AAAA) + { + type = "AAAA"; + host = rr.RecordName; + data = rr.RecordData; + } else if (rr.RecordType == DnsRecordType.NS) { type = "NS"; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS/MsDNS.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS/MsDNS.cs index e2a81904..2c84d242 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS/MsDNS.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS/MsDNS.cs @@ -130,6 +130,8 @@ namespace WebsitePanel.Providers.DNS ManagementObjectCollection rrsA = wmi.GetWmiObjects("MicrosoftDNS_AType", "DomainName='{0}'", zoneName); + ManagementObjectCollection rrsAAAA = wmi.GetWmiObjects("MicrosoftDNS_AAAAType", "DomainName='{0}'", zoneName); + ManagementObjectCollection rrsCNAME = wmi.GetWmiObjects("MicrosoftDNS_CNAMEType", "DomainName='{0}'", zoneName); ManagementObjectCollection rrsMX = wmi.GetWmiObjects("MicrosoftDNS_MXType", "DomainName='{0}'", zoneName); @@ -150,6 +152,14 @@ namespace WebsitePanel.Providers.DNS records.Add(record); } + foreach (ManagementObject rr in rrsAAAA) { + record = new DnsRecord(); + record.RecordType = DnsRecordType.AAAA; + record.RecordName = CorrectHost(zoneName, (string)rr.Properties["OwnerName"].Value); + record.RecordData = (string)rr.Properties["RecordData"].Value; + records.Add(record); + } + foreach (ManagementObject rr in rrsCNAME) { record = new DnsRecord(); @@ -390,7 +400,9 @@ namespace WebsitePanel.Providers.DNS { if (record.RecordType == DnsRecordType.A) AddARecord(zoneName, record.RecordName, record.RecordData); - else if (record.RecordType == DnsRecordType.CNAME) + else if (record.RecordType == DnsRecordType.AAAA) + AddAAAARecord(zoneName, record.RecordName, record.RecordData); + else if (record.RecordType == DnsRecordType.CNAME) AddCNameRecord(zoneName, record.RecordName, record.RecordData); else if (record.RecordType == DnsRecordType.MX) AddMXRecord(zoneName, record.RecordName, record.RecordData, record.MxPriority); @@ -420,7 +432,9 @@ namespace WebsitePanel.Providers.DNS { if (record.RecordType == DnsRecordType.A) DeleteARecord(zoneName, record.RecordName, record.RecordData); - else if (record.RecordType == DnsRecordType.CNAME) + else if (record.RecordType == DnsRecordType.AAAA) + DeleteAAAARecord(zoneName, record.RecordName, record.RecordData); + else if (record.RecordType == DnsRecordType.CNAME) DeleteCNameRecord(zoneName, record.RecordName, record.RecordData); else if (record.RecordType == DnsRecordType.MX) DeleteMXRecord(zoneName, record.RecordName, record.RecordData); @@ -625,6 +639,57 @@ namespace WebsitePanel.Providers.DNS } #endregion + #region AAAA Record + /// + /// + /// + /// + /// + /// + /// Supports managed resources disposal + private void AddAAAARecord(string zoneName, string host, string ip) { + // add record + using (ManagementClass clsRR = wmi.GetClass("MicrosoftDNS_AAAAType")) { + clsRR.InvokeMethod("CreateInstanceFromPropertyData", new object[] { + GetDnsServerName(), + zoneName, + CorrectHostName(zoneName, host), + 1, + MinimumTTL, + ip + }); + } + + // update SOA record + if (bulkRecords) return; + UpdateSoaRecord(zoneName); + } + + /// + /// Supports managed resources disposal + /// + /// + /// + /// + private void DeleteAAAARecord(string zoneName, string host, string ip) { + string query = String.Format("SELECT * FROM MicrosoftDNS_AAAAType " + + "WHERE ContainerName = '{0}' AND OwnerName = '{1}'", + zoneName, CorrectHostName(zoneName, host)); + + if (ip != null) + query += String.Format(" AND RecordData = '{0}'", ip); + + using (ManagementObjectCollection objRRs = wmi.ExecuteQuery(query)) { + foreach (ManagementObject objRR in objRRs) using (objRR) + objRR.Delete(); + } + + // update SOA record + UpdateSoaRecord(zoneName); + + } + #endregion + #region CNAME Record /// /// diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Nettica/Nettica.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Nettica/Nettica.cs index 2ba41bf0..e299baa0 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Nettica/Nettica.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.Nettica/Nettica.cs @@ -101,6 +101,9 @@ namespace WebsitePanel.Providers.DNS case "A": dnsRecord.RecordType = DnsRecordType.A; break; + case "AAAA": + dnsRecord.RecordType = DnsRecordType.AAAA; + break; case "MX": dnsRecord.RecordType = DnsRecordType.MX; break; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.PowerDNS/PowerDNS.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.PowerDNS/PowerDNS.cs index 8f1e419d..74054e0c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.PowerDNS/PowerDNS.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.PowerDNS/PowerDNS.cs @@ -1060,7 +1060,11 @@ namespace WebsitePanel.Providers.DNS result = DnsRecordType.A; break; - case "CNAME": + case "AAAA": + result = DnsRecordType.AAAA; + break; + + case "CNAME": result = DnsRecordType.CNAME; break; @@ -1097,7 +1101,11 @@ namespace WebsitePanel.Providers.DNS case DnsRecordType.A: result = "A"; break; - + + case DnsRecordType.AAAA: + result = "AAAA"; + break; + case DnsRecordType.CNAME: result = "CNAME"; break; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS/SimpleDNS.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS/SimpleDNS.cs index 6778f83f..d17d39b8 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS/SimpleDNS.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS/SimpleDNS.cs @@ -190,6 +190,8 @@ namespace WebsitePanel.Providers.DNS { if (record.RecordType == DnsRecordType.A) AddARecord(zoneName, record.RecordName, record.RecordData); + else if (record.RecordType == DnsRecordType.AAAA) + AddAAAARecord(zoneName, record.RecordName, record.RecordData); else if (record.RecordType == DnsRecordType.CNAME) AddCNameRecord(zoneName, record.RecordName, record.RecordData); else if (record.RecordType == DnsRecordType.MX) @@ -225,7 +227,7 @@ namespace WebsitePanel.Providers.DNS { try { - if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.CNAME) + if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.AAAA || record.RecordType == DnsRecordType.CNAME) record.RecordName = CorrectRecordName(zoneName, record.RecordName); // delete record @@ -254,7 +256,7 @@ namespace WebsitePanel.Providers.DNS } #endregion - #region A records + #region A & AAAA records private void AddARecord(string zoneName, string host, string ip) { // get all zone records @@ -285,6 +287,34 @@ namespace WebsitePanel.Providers.DNS UpdateZone(zoneName, records); } + private void AddAAAARecord(string zoneName, string host, string ip) { + // get all zone records + List records = GetZoneRecordsArrayList(zoneName); + + // delete AAAA record + //DeleteARecordInternal(records, zoneName, host); + + //check if user tries to add existent zone record + foreach (DnsRecord dnsRecord in records) { + if ((String.Compare(dnsRecord.RecordName, host, StringComparison.OrdinalIgnoreCase) == 0) + && (String.Compare(dnsRecord.RecordData, ip, StringComparison.OrdinalIgnoreCase) == 0) + ) + + + return; + } + + // add new AAAA record + DnsRecord record = new DnsRecord(); + record.RecordType = DnsRecordType.AAAA; + record.RecordName = host; + record.RecordData = ip; + records.Add(record); + + // update zone + UpdateZone(zoneName, records); + } + private void DeleteRecord(string zoneName, DnsRecordType recordType, string recordName, string recordData) { @@ -576,6 +606,15 @@ namespace WebsitePanel.Providers.DNS r.RecordText = zfLine; records.Add(r); } + else if (recordType == "AAAA") // A record + { + DnsRecord r = new DnsRecord(); + r.RecordType = DnsRecordType.AAAA; + r.RecordName = CorrectRecordName(zoneName, recordName); + r.RecordData = recordData; + r.RecordText = zfLine; + records.Add(r); + } else if (recordType == "CNAME") // CNAME record { DnsRecord r = new DnsRecord(); @@ -696,6 +735,12 @@ namespace WebsitePanel.Providers.DNS data = rr.RecordData; name = BuildRecordName(zoneName, host); } + else if (rr.RecordType == DnsRecordType.AAAA) { + type = "AAAA"; + host = rr.RecordName; + data = rr.RecordData; + name = BuildRecordName(zoneName, host); + } else if (rr.RecordType == DnsRecordType.NS) { type = "NS"; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS50/SimpleDNS5.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS50/SimpleDNS5.cs index a921c7da..d654e515 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS50/SimpleDNS5.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.SimpleDNS50/SimpleDNS5.cs @@ -89,6 +89,8 @@ namespace WebsitePanel.Providers.DNS { // A record { DnsRecordType.A, new BuildDnsRecordDataEventHandler(BuildRecordData_ARecord) }, + // AAAA record + { DnsRecordType.AAAA, new BuildDnsRecordDataEventHandler(BuildRecordData_AAAARecord) }, // NS record { DnsRecordType.NS, new BuildDnsRecordDataEventHandler(BuildRecordData_NSRecord) }, // CNAME @@ -148,6 +150,13 @@ namespace WebsitePanel.Providers.DNS RecordData = record.DataFields[0] }; break; + case "AAAA": + dnsRecord = new DnsRecord { + RecordName = recordName, + RecordType = DnsRecordType.AAAA, + RecordData = record.DataFields[0] + }; + break; case "NS": dnsRecord = new DnsRecord { @@ -531,6 +540,12 @@ namespace WebsitePanel.Providers.DNS // dnsZone.Records.Add(m_strRecordName, "A", rr.RecordData); break; + case DnsRecordType.AAAA: + // cleanup DNS record if exists + dnsZone.Records.Remove(m_strRecordName, "AAAA"); + // + dnsZone.Records.Add(m_strRecordName, "AAAA", rr.RecordData); + break; case DnsRecordType.NS: // cleanup DNS record if exists dnsZone.Records.Remove(m_strRecordName, "NS"); @@ -583,6 +598,8 @@ namespace WebsitePanel.Providers.DNS { if (r_type == DnsRecordType.A) return "A"; + else if (r_type == DnsRecordType.AAAA) + return "AAAA"; else if (r_type == DnsRecordType.CNAME) return "CNAME"; else if (r_type == DnsRecordType.MX) @@ -610,6 +627,13 @@ namespace WebsitePanel.Providers.DNS data.Add(record.RecordData); } + static void BuildRecordData_AAAARecord(string zoneName, ref string type, + DnsRecord record, List data) + { + type = "AAAA"; + data.Add(record.RecordData); + } + static void BuildRecordData_NSRecord(string zoneName, ref string type, DnsRecord record, List data) { diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/SiteSettings.config b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/SiteSettings.config index 0a99be01..d13068b7 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/SiteSettings.config +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/SiteSettings.config @@ -1,40 +1,40 @@  - - WebsitePanel - - http://localhost:9002 - - UserCulture - UserTheme - - - - - - - - - - - - - - - Home - Login - Home - UserCustomers - SpaceHome - NestedSpaces - SearchUsers - SearchSpaces - LoggedUserDetails - - Browse2.ascx - Browse.ascx - Edit.ascx - Edit.ascx - - false - + + WebsitePanel + + http://localhost:9005 + + UserCulture + UserTheme + + + + + + + + + + + + + + + Home + Login + Home + UserCustomers + SpaceHome + NestedSpaces + SearchUsers + SearchSpaces + LoggedUserDetails + + Browse2.ascx + Browse.ascx + Edit.ascx + Edit.ascx + + false + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj index cf0ab446..89669cd7 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj @@ -112,36 +112,42 @@ BillingCycles.ascx + ASPXCodeBehind BillingCycles.ascx BillingCyclesAddCycle.ascx + ASPXCodeBehind BillingCyclesAddCycle.ascx BillingCyclesEditCycle.ascx + ASPXCodeBehind BillingCyclesEditCycle.ascx Categories.ascx + ASPXCodeBehind Categories.ascx CategoriesAddCategory.ascx + ASPXCodeBehind CategoriesAddCategory.ascx CategoriesEditCategory.ascx + ASPXCodeBehind CategoriesEditCategory.ascx @@ -153,8 +159,12 @@ ASPXCodeBehind - - + + ASPXCodeBehind + + + ASPXCodeBehind + @@ -181,150 +191,175 @@ CustomerPaymentProfile.ascx + ASPXCodeBehind CustomerPaymentProfile.ascx CustomersInvoices.ascx + ASPXCodeBehind CustomersInvoices.ascx CustomersInvoicesViewInvoice.ascx + ASPXCodeBehind CustomersInvoicesViewInvoice.ascx CustomersPayments.ascx + ASPXCodeBehind CustomersPayments.ascx CustomersServices.ascx + ASPXCodeBehind CustomersServices.ascx CustomersServicesUpgradeService.ascx + ASPXCodeBehind CustomersServicesUpgradeService.ascx CustomersServicesViewService.ascx + ASPXCodeBehind CustomersServicesViewService.ascx DomainNames.ascx + ASPXCodeBehind DomainNames.ascx DomainNamesAddDomain.ascx + ASPXCodeBehind DomainNamesAddDomain.ascx DomainNamesEditDomain.ascx + ASPXCodeBehind DomainNamesEditDomain.ascx DomainRegistrarDirecti.ascx + ASPXCodeBehind DomainRegistrarDirecti.ascx DomainRegistrarEnom.ascx + ASPXCodeBehind DomainRegistrarEnom.ascx EcommerceSystemSettings.ascx + ASPXCodeBehind EcommerceSystemSettings.ascx HostingAddons.ascx + ASPXCodeBehind HostingAddons.ascx HostingAddonsAddAddon.ascx + ASPXCodeBehind HostingAddonsAddAddon.ascx HostingAddonsEditAddon.ascx + ASPXCodeBehind HostingAddonsEditAddon.ascx HostingPlans.ascx + ASPXCodeBehind HostingPlans.ascx HostingPlansAddPlan.ascx + ASPXCodeBehind HostingPlansAddPlan.ascx HostingPlansEditPlan.ascx + ASPXCodeBehind HostingPlansEditPlan.ascx NotificationNewInvoice.ascx + ASPXCodeBehind NotificationNewInvoice.ascx NotificationPaymentReceived.ascx + ASPXCodeBehind NotificationPaymentReceived.ascx NotificationServiceActivated.ascx + ASPXCodeBehind NotificationServiceActivated.ascx NotificationServiceCancelled.ascx + ASPXCodeBehind NotificationServiceCancelled.ascx NotificationServiceSuspended.ascx + ASPXCodeBehind NotificationServiceSuspended.ascx OrderFailed.ascx + ASPXCodeBehind OrderFailed.ascx @@ -338,48 +373,56 @@ PaymentMethod2Checkout.ascx + ASPXCodeBehind PaymentMethod2Checkout.ascx PaymentMethodCreditCard.ascx + ASPXCodeBehind PaymentMethodCreditCard.ascx PaymentMethodOffline.ascx + ASPXCodeBehind PaymentMethodOffline.ascx PaymentMethodPayPalAccount.ascx + ASPXCodeBehind PaymentMethodPayPalAccount.ascx 2CO_Payment.ascx + ASPXCodeBehind 2CO_Payment.ascx CreditCard_Payment.ascx + ASPXCodeBehind CreditCard_Payment.ascx Offline_Payment.ascx + ASPXCodeBehind Offline_Payment.ascx PPAccount_Payment.ascx + ASPXCodeBehind PPAccount_Payment.ascx @@ -393,30 +436,35 @@ DomainName_ServiceDetails.ascx + ASPXCodeBehind DomainName_ServiceDetails.ascx HostingAddon_ServiceDetails.ascx + ASPXCodeBehind HostingAddon_ServiceDetails.ascx HostingPlan_Brief.ascx + ASPXCodeBehind HostingPlan_Brief.ascx HostingPlan_Highlights.ascx + ASPXCodeBehind HostingPlan_Highlights.ascx HostingPlan_ServiceDetails.ascx + ASPXCodeBehind HostingPlan_ServiceDetails.ascx @@ -424,24 +472,28 @@ ProvisioningSettingsEdit.ascx + ASPXCodeBehind ProvisioningSettingsEdit.ascx QuickSignup.ascx + ASPXCodeBehind QuickSignup.ascx OrderComplete.ascx + ASPXCodeBehind OrderComplete.ascx OrderCheckout.ascx + ASPXCodeBehind OrderCheckout.ascx @@ -453,102 +505,119 @@ CatalogBreadCrumb.ascx + ASPXCodeBehind CatalogBreadCrumb.ascx StorefrontMenu.ascx + ASPXCodeBehind StorefrontMenu.ascx StorefrontOrderProduct.ascx + ASPXCodeBehind StorefrontOrderProduct.ascx StorefrontViewCategory.ascx + ASPXCodeBehind StorefrontViewCategory.ascx StorefrontWelcome.ascx + ASPXCodeBehind StorefrontWelcome.ascx StorefrontWelcomeEdit.ascx + ASPXCodeBehind StorefrontWelcomeEdit.ascx 2Checkout_Settings.ascx + ASPXCodeBehind 2Checkout_Settings.ascx AuthorizeNet_Settings.ascx + ASPXCodeBehind AuthorizeNet_Settings.ascx OfflinePayment_Settings.ascx + ASPXCodeBehind OfflinePayment_Settings.ascx PayPalPro_Settings.ascx + ASPXCodeBehind PayPalPro_Settings.ascx PayPalStandard_Settings.ascx + ASPXCodeBehind PayPalStandard_Settings.ascx Taxations.ascx + ASPXCodeBehind Taxations.ascx TaxationsAddTax.ascx + ASPXCodeBehind TaxationsAddTax.ascx TaxationsEditTax.ascx + ASPXCodeBehind TaxationsEditTax.ascx TermsAndConditions.ascx + ASPXCodeBehind TermsAndConditions.ascx TermsAndConditionsEdit.ascx + ASPXCodeBehind TermsAndConditionsEdit.ascx AddonProducts.ascx + ASPXCodeBehind AddonProducts.ascx @@ -565,120 +634,140 @@ ChoosePaymentMethod.ascx + ASPXCodeBehind ChoosePaymentMethod.ascx CreateUserAccount.ascx + ASPXCodeBehind CreateUserAccount.ascx CustomerInvoiceTemplated.ascx + ASPXCodeBehind CustomerInvoiceTemplated.ascx DomainNameBillingCycles.ascx + ASPXCodeBehind DomainNameBillingCycles.ascx EmailNotificationEditor.ascx + ASPXCodeBehind EmailNotificationEditor.ascx HostingAddonOneTimeFee.ascx + ASPXCodeBehind HostingAddonOneTimeFee.ascx HostingPlanBillingCycles.ascx + ASPXCodeBehind HostingPlanBillingCycles.ascx HostingPlanQuotas.ascx + ASPXCodeBehind HostingPlanQuotas.ascx LoginUserAccount.ascx + ASPXCodeBehind LoginUserAccount.ascx ManualPaymentAdd.ascx + ASPXCodeBehind ManualPaymentAdd.ascx PlanDomainOption.ascx + ASPXCodeBehind PlanDomainOption.ascx PlanHostingAddons.ascx + ASPXCodeBehind PlanHostingAddons.ascx ProductHighlights.ascx + ASPXCodeBehind ProductHighlights.ascx QuickHostingAddon.ascx + ASPXCodeBehind QuickHostingAddon.ascx QuickHostingPlanCycles.ascx + ASPXCodeBehind QuickHostingPlanCycles.ascx QuickHostingPlans.ascx + ASPXCodeBehind QuickHostingPlans.ascx PathBreadCrumb.ascx + ASPXCodeBehind PathBreadCrumb.ascx ProductCategories.ascx + ASPXCodeBehind ProductCategories.ascx UserAccountDetails.ascx + ASPXCodeBehind UserAccountDetails.ascx ViewProductDetails.ascx + ASPXCodeBehind ViewProductDetails.ascx diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx index 81ff9687..ca36fdd0 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx @@ -73,6 +73,7 @@ function confirmation() A + AAAA MX NS TXT @@ -89,11 +90,11 @@ function confirmation() - + - + @@ -102,14 +103,14 @@ function confirmation() + ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic" /> + ErrorMessage="*" ValidationExpression="\d{1,3}" ValidationGroup="DnsZoneRecord" />
- +
\ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.cs index a4f1e1f2..a2bc5de3 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.cs @@ -109,6 +109,11 @@ namespace WebsitePanel.Portal lblRecordData.Text = "IP:"; IPValidator.Enabled = true; } + else if (ddlRecordType.SelectedValue == "AAAA") + { + lblRecordData.Text = "IP (v6):"; + IPValidator.Enabled = true; + } else { lblRecordData.Text = "Record Data:"; @@ -116,6 +121,14 @@ namespace WebsitePanel.Portal } } + protected void Validate(object source, ServerValidateEventArgs args) { + var ip = args.Value; + System.Net.IPAddress ipaddr; + args.IsValid = System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) && + ((ddlRecordType.SelectedValue == "A" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) || + (ddlRecordType.SelectedValue == "AAAA" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)); + } + private void SaveRecord() { if (Page.IsValid) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.designer.cs index 88859342..45ed008c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/DnsZoneRecords.ascx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3074 // // Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -173,7 +172,7 @@ namespace WebsitePanel.Portal { /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::System.Web.UI.WebControls.RegularExpressionValidator IPValidator; + protected global::System.Web.UI.WebControls.CustomValidator IPValidator; /// /// rowMXPriority control. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx index 68d67f1e..119a78c4 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx @@ -113,6 +113,7 @@ A + AAAA MX NS TXT @@ -129,14 +130,14 @@ - + - + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.cs index b43ebb7a..7d383374 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.cs @@ -110,15 +110,27 @@ namespace WebsitePanel.Portal.ExchangeServer if (ddlRecordType.SelectedValue == "A") { lblRecordData.Text = "IP:"; - IPValidator1.Enabled = true; - } + IPValidator.Enabled = true; + } + else if (ddlRecordType.SelectedValue == "AAAA") { + lblRecordData.Text = "IPv6:"; + IPValidator.Enabled = true; + } else { lblRecordData.Text = "Record Data:"; - IPValidator1.Enabled = false; + IPValidator.Enabled = false; } } + protected void Validate(object source, ServerValidateEventArgs args) { + var ip = args.Value; + System.Net.IPAddress ipaddr; + args.IsValid = System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) && + ((ddlRecordType.SelectedValue == "A" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) || + (ddlRecordType.SelectedValue == "AAAA" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)); + } + private void SaveRecord() { if (!Page.IsValid) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.designer.cs index d9cc5277..dc7f8ea9 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainRecords.ascx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1433 // // Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -230,13 +229,13 @@ namespace WebsitePanel.Portal.ExchangeServer { protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireData; /// - /// IPValidator1 control. + /// IPValidator control. /// /// /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::System.Web.UI.WebControls.RegularExpressionValidator IPValidator1; + protected global::System.Web.UI.WebControls.CustomValidator IPValidator; /// /// rowMXPriority control. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx index bf9d97f3..199ca563 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx @@ -35,6 +35,7 @@ A + AAAA MX NS TXT @@ -51,13 +52,21 @@ - + + + + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.cs index 5d03772c..eeda4be7 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.cs @@ -138,13 +138,33 @@ namespace WebsitePanel.Portal private void ToggleRecordControls() { - ipAddress.Visible = (ddlRecordType.SelectedValue == "A"); - //rowData.Visible = (ddlRecordType.SelectedValue != "A"); + ipAddress.Visible = (ddlRecordType.SelectedValue == "A" || ddlRecordType.SelectedValue == "AAAA"); + //rowData.Visible = (ddlRecordType.SelectedValue != "A" && ddlRecordType.SelectedValue != "AAAA"); rowMXPriority.Visible = (ddlRecordType.SelectedValue == "MX"); + if (ddlRecordType.SelectedValue == "A") { + lblRecordData.Text = "IP:"; + IPValidator.Enabled = true; + } else if (ddlRecordType.SelectedValue == "AAAA") { + lblRecordData.Text = "IP (v6):"; + IPValidator.Enabled = true; + } else { + lblRecordData.Text = "Record Data:"; + IPValidator.Enabled = false; + } } + protected void Validate(object source, ServerValidateEventArgs args) { + var ip = args.Value; + System.Net.IPAddress ipaddr; + args.IsValid = System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) && + ((ddlRecordType.SelectedValue == "A" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) || + (ddlRecordType.SelectedValue == "AAAA" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)); + } + private void SaveRecord() { + if (!Page.IsValid) return; + GlobalDnsRecord record = new GlobalDnsRecord(); record.RecordId = (int)ViewState["RecordID"]; record.RecordType = ddlRecordType.SelectedValue; diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs index d9fbff7f..ce152043 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs @@ -1,32 +1,204 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.42 // // Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// the code is regenerated. // //------------------------------------------------------------------------------ namespace WebsitePanel.Portal { + public partial class GlobalDnsRecordsControl { - protected System.Web.UI.WebControls.Panel pnlRecords; - protected System.Web.UI.WebControls.Button btnAdd; - protected System.Web.UI.WebControls.GridView gvRecords; - protected System.Web.UI.WebControls.Panel pnlEdit; - protected System.Web.UI.WebControls.Label lblRecordType; - protected System.Web.UI.WebControls.DropDownList ddlRecordType; - protected System.Web.UI.WebControls.Label lblRecordName; - protected System.Web.UI.WebControls.TextBox txtRecordName; - protected System.Web.UI.HtmlControls.HtmlTableRow rowData; - protected System.Web.UI.WebControls.Label lblRecordData; - protected System.Web.UI.WebControls.TextBox txtRecordData; - protected WebsitePanel.Portal.SelectIPAddress ipAddress; - protected System.Web.UI.HtmlControls.HtmlTableRow rowMXPriority; - protected System.Web.UI.WebControls.Label lblMXPriority; - protected System.Web.UI.WebControls.TextBox txtMXPriority; - protected System.Web.UI.WebControls.Button btnSave; - protected System.Web.UI.WebControls.Button btnCancel; + + /// + /// pnlRecords control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel pnlRecords; + + /// + /// btnAdd control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnAdd; + + /// + /// gvRecords control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.GridView gvRecords; + + /// + /// pnlEdit control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel pnlEdit; + + /// + /// lblRecordType control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblRecordType; + + /// + /// ddlRecordType control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddlRecordType; + + /// + /// lblRecordName control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblRecordName; + + /// + /// txtRecordName control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtRecordName; + + /// + /// rowData control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow rowData; + + /// + /// lblRecordData control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblRecordData; + + /// + /// txtRecordData control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtRecordData; + + /// + /// ipAddress control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.SelectIPAddress ipAddress; + + /// + /// valRequireData control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireData; + + /// + /// IPValidator control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CustomValidator IPValidator; + + /// + /// rowMXPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow rowMXPriority; + + /// + /// lblMXPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblMXPriority; + + /// + /// txtMXPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtMXPriority; + + /// + /// valRequireMxPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireMxPriority; + + /// + /// valRequireCorrectPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valRequireCorrectPriority; + + /// + /// btnSave control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnSave; + + /// + /// btnCancel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnCancel; } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx index 22cfab3e..fccfa243 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx @@ -8,7 +8,9 @@ - + + +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.cs index 7eef428c..241e9da4 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.cs @@ -49,6 +49,7 @@ namespace WebsitePanel.Portal { if (!IsPostBack) { + // bind dropdowns try { @@ -96,7 +97,7 @@ namespace WebsitePanel.Portal string comments = txtComments.Text.Trim(); // add ip address - if (endIP.Text != "") + if (endIP.Text != "" || startIP.Text.Contains("/")) { try { @@ -162,5 +163,12 @@ namespace WebsitePanel.Portal SubnetRow.Visible = vps; GatewayRow.Visible = vps; } + + public void CheckIPAddresses(object sender, ServerValidateEventArgs args) { + startIP.Validate(sender, args); + endIP.Validate(sender, args); + subnetMask.Validate(sender, args); + args.IsValid = startIP.IsV6 == endIP.IsV6 && (startIP.IsV6 == subnetMask.IsV6 || subnetMask.IsMask); + } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.designer.cs index aee0b166..3e04a209 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddressesAddIPAddress.ascx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1434 // // Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -31,6 +30,15 @@ namespace WebsitePanel.Portal { /// protected global::System.Web.UI.WebControls.ValidationSummary validatorsSummary; + /// + /// consistent Addresses control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CustomValidator consistentAddresses; + /// /// locPool control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx index ac0b0237..4077f5a1 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx @@ -288,7 +288,7 @@ diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx.designer.cs index 8b931880..60f2a3c5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/HyperV_Settings.ascx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.4927 // // Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// the code is regenerated. // //------------------------------------------------------------------------------ diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx index dca8fa1f..73881456 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx @@ -1,8 +1,5 @@ <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditIPAddressControl.ascx.cs" Inherits="WebsitePanel.Portal.UserControls.EditIPAddressControl" %> - + - - \ No newline at end of file + ControlToValidate="txtAddress" SetFocusOnError="true" Text="*" Enabled="false" Display="Dynamic" /> + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.cs index c979f0b7..751a59da 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.cs @@ -34,8 +34,16 @@ using System.Web.UI.WebControls; namespace WebsitePanel.Portal.UserControls { + [Flags] + public enum IPValidationMode { V4 = 1, V6 = 2, V4AndV6 = 3 }; + public partial class EditIPAddressControl : WebsitePanelControlBase { + + public IPValidationMode Validation { get; set; } + + public EditIPAddressControl() { Validation = IPValidationMode.V4AndV6; AllowSubnet = false; } + public bool Required { get { return requireAddressValidator.Enabled; } @@ -86,5 +94,30 @@ namespace WebsitePanel.Portal.UserControls { } + + public bool AllowSubnet { get; set; } + public bool IsV6 { get; private set; } + public bool IsMask { get; private set; } + + public void Validate(object source, ServerValidateEventArgs args) { + IsMask = IsV6 = false; + var ip = args.Value; + int net = 0; + if (ip.Contains("/")) { + args.IsValid = AllowSubnet; + var tokens = ip.Split('/'); + ip = tokens[0]; + args.IsValid &= int.TryParse(tokens[1], out net) && net <= 128; + if (string.IsNullOrEmpty(ip)) { + IsMask = true; + return; + } + } + System.Net.IPAddress ipaddr; + args.IsValid &= System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) && + (((Validation & IPValidationMode.V6) != 0 && (IsV6 = ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)) || + ((Validation & IPValidationMode.V4) != 0 && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)); + args.IsValid &= ipaddr.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork || net < 32; + } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.designer.cs index 2f6f62b6..83559696 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/EditIPAddressControl.ascx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1434 // // Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -38,6 +37,6 @@ namespace WebsitePanel.Portal.UserControls { /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::System.Web.UI.WebControls.RegularExpressionValidator addressValidator; + protected global::System.Web.UI.WebControls.CustomValidator addressValidator; } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Web.config b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Web.config index 39876a11..6263a174 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Web.config @@ -1,12 +1,11 @@ - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj index 8e5646ec..b7f1a19d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj @@ -18,7 +18,7 @@ v4.0 - false + true true @@ -690,11 +690,11 @@ - False + True False - 9001 + 9021 / - http://localhost/WebPortal + http://localhost:9021/ False False
@@ -33,7 +35,7 @@ - +    @@ -52,7 +54,7 @@
- +
/ - +