using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net.NetworkInformation; namespace InABox.Core { public static class LicenseUtils { #region Mac Addresses public static String[] GetMacAddresses() { return NetworkInterface .GetAllNetworkInterfaces() .Where(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback) .Select(nic => nic.GetPhysicalAddress().ToString()).ToArray(); } public static bool ValidateMacAddresses(String[] addresses) { var hardware = GetMacAddresses(); return hardware.Any(addresses.Contains); } #endregion #region License Generation public static LicenseData RenewLicense(LicenseData oldLicense, DateTime renewed, DateTime newExpiry, DateTime renewAvailable, String[] addresses) { return new LicenseData { LastRenewal = renewed, Expiry = newExpiry, CustomerID = oldLicense?.CustomerID ?? Guid.Empty, RenewalAvailable = renewAvailable, Addresses = addresses, IsDynamic = oldLicense?.IsDynamic ?? false }; } private static readonly byte[] LicenseKey = Convert.FromBase64String("dCyTyQkj1o1rqJJQlT+Jcnkxr+OQnO4KCoF/b+6cx54="); public static string? EncryptLicenseRequest(LicenseRequest request) { return Encryption.EncryptV2(Serialization.Serialize(request), LicenseKey); } public static bool TryEncryptLicenseRequest(LicenseRequest request, [NotNullWhen(true)] out string? result, [NotNullWhen(false)] out string? error) { return Encryption.TryEncryptV2(Serialization.Serialize(request), LicenseKey, out result, out error); } /// /// Decrypts . /// /// The request to decrypt. /// /// The new license request, or if errors occurred. /// public static bool TryDecryptLicenseRequest(string data, [NotNullWhen(true)] out LicenseRequest? result, [NotNullWhen(false)] out string? error) { if (!Encryption.TryDecryptV2(data, LicenseKey, out var decrypted, out error)) { result = null; return false; } result = Serialization.Deserialize(decrypted); if(result == null) { error = "Request deserialization failed"; return false; } return true; } /// /// Decrypts , throwing an on fail. /// /// The data to decrypt. /// /// The new license request. /// public static LicenseRequest DecryptLicenseRequest(string data) { if (!TryDecryptLicenseRequest(data, out var result, out var error)) throw new Exception(error); return result; } /// /// Encrypts the license data. /// /// The license to encrypt. /// /// The encrypted data. /// public static string? EncryptLicense(LicenseData license) { return Encryption.EncryptV2(Serialization.Serialize(license), LicenseKey); } public static bool TryEncryptLicense(LicenseData license, [NotNullWhen(true)] out string? result, [NotNullWhen(false)] out string? error) { return Encryption.TryEncryptV2(Serialization.Serialize(license), LicenseKey, out result, out error); } /// /// Decrypts . /// /// The license to decrypt. /// /// The new license data, or if errors occurred. /// public static bool TryDecryptLicense(string data, [NotNullWhen(true)] out LicenseData? result, [NotNullWhen(false)] out string? error) { if (!Encryption.TryDecryptV2(data, LicenseKey, out var decrypted, out error)) { result = null; return false; } result = Serialization.Deserialize(decrypted); if(result == null) { error = "License deserialization failed"; return false; } return true; } /// /// Decrypts , throwing an on fail. /// /// The license to decrypt. /// /// The new license data. /// public static LicenseData DecryptLicense(string data) { if (!TryDecryptLicense(data, out var result, out var error)) throw new Exception(error); return result; } #endregion #region Fees & Discounts private static readonly Dictionary _licensefees = new Dictionary(); private static readonly Dictionary _periods = new Dictionary(); private static readonly Dictionary _userDiscounts = new Dictionary(); public static double GetLicenseFee(String type) { return _licensefees.GetValueOrDefault(type, 0); } public static double GetLicenseFee() where T : LicenseToken { return GetLicenseFee(typeof(T).EntityName()); } public static IEnumerable LicenseTypes() { return _licensefees.Keys; } public static double GetUserDiscount(int users) { var key = _userDiscounts.Keys .Where(x => x <= users) .DefaultIfEmpty(-1) .Max(); if (key == -1) return 0; return _userDiscounts[key]; } public static double GetTimeDiscount(int months) { var period = _periods.Keys .Where(x => x <= months) .DefaultIfEmpty(-1) .Max(); if (period == -1) return 0; return _periods[period]; } public static IEnumerable TimeDiscountLevels() { return _periods.Keys; } public static double CalculateLicenseFee(Dictionary licenses, int time) { double licensefee = 0.00F; foreach (var license in licenses.Keys) if (_licensefees.ContainsKey(license)) licensefee += _licensefees[license] * licenses[license]; var users = licenses.Values.OrderBy(x => x).LastOrDefault(); var userdiscount = GetUserDiscount(users); var timediscount = GetTimeDiscount(time); var result = licensefee * ((100.0F - userdiscount) / 100.0F) * ((100.0F - timediscount) / 100.0F); return result; } public static void LoadSummary(LicenseFeeResponse feeResponse) { _licensefees.Clear(); _periods.Clear(); _userDiscounts.Clear(); foreach (var license in feeResponse.LicenseFees) _licensefees[license.Key] = license.Value; foreach (var (months, period) in feeResponse.TimeDiscounts) _periods[months] = period; foreach (var (users, discount) in feeResponse.UserDiscounts) _userDiscounts[users] = discount; } /// /// Gets a map from entities to their associated licenses. /// /// A map of entity types to license types. public static Dictionary LicenseMap() { var result = new Dictionary(); var entities = CoreUtils.Entities.Where(x => x.IsClass && !x.IsGenericType && x.IsSubclassOf(typeof(Entity))); foreach (var entity in entities) { var lic = entity.GetInterfaces() .FirstOrDefault(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(ILicense<>)); if (lic != null) result[entity] = lic.GenericTypeArguments.FirstOrDefault(); } return result; } public static void SaveLicenseSummary(string filename) { var entitymap = LicenseMap(); var summary = new List { "\"License Token\",\"Class Name\"" }; foreach (var mapentry in entitymap.OrderBy(x => x.Value)) summary.Add(string.Format("\"{0}\",\"{1}\"", mapentry.Value?.GetCaption(), mapentry.Value.EntityName())); File.WriteAllLines(filename, summary.ToArray()); } public static void Reset() { _licensefees.Clear(); _periods.Clear(); _userDiscounts.Clear(); } #endregion } public class LicenseFeeRequest { public Guid RegistrationID { get; set; } } public class LicenseFeeResponse { public LicenseFeeResponse() { LicenseFees = new Dictionary(); TimeDiscounts = new Dictionary(); UserDiscounts = new Dictionary(); } public Dictionary LicenseFees { get; set; } public Dictionary TimeDiscounts { get; set; } public Dictionary UserDiscounts { get; set; } } }