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