LicenseManager.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. namespace Vinno.vCloud.Common.License.Licenses
  7. {
  8. /// <summary>
  9. /// Manager License record, includes create, update ,check license and etc.
  10. /// </summary>
  11. public class LicenseManager : IDisposable
  12. {
  13. #region CurrentLicense Method
  14. /// <summary>
  15. /// Current CurrentLicense Version
  16. /// </summary>
  17. public static string CurrentVersion => "1.0.0";
  18. private License _currentLicense;
  19. /// <summary>
  20. /// "FirstStartUpTimeFileName"
  21. /// </summary>
  22. private string startupFileName = "6ea2ed30fd97d3a907557904e1038a3e.vl";
  23. /// <summary>
  24. /// Gets or Sets a vlaue that the current license
  25. /// </summary>
  26. public License CurrentLicense
  27. {
  28. get => _currentLicense;
  29. set => _currentLicense = value;
  30. }
  31. /// <summary>
  32. ///Gets or Sets a vlaue that first StartTime Licnese
  33. /// </summary>
  34. internal StartupLicnese StartupLicnese { get; private set; }
  35. /// <summary>
  36. ///Gets VerifyResult when Verify current us count
  37. /// </summary>
  38. /// <param name="uscount">current us count</param>
  39. /// <returns>None : No Current CurrentLicense,FailAndExceedMaxUsCount: CurrentLicense.MaxUsCount> uscount,Successd: uscount>_currentLicense.MaxUsCount </returns>
  40. public VerifyResult VerifyMaxUsCount(int uscount)
  41. {
  42. if (_currentLicense == null)
  43. {
  44. return VerifyResult.None;
  45. }
  46. return _currentLicense.MaxUsCount > uscount ? VerifyResult.Succeeded : VerifyResult.FailAndExceedMaxUsCount;
  47. }
  48. /// <summary>
  49. /// Gets VerifyResult when Verify current Account Count
  50. /// </summary>
  51. /// <param name="accountCount">current used account Count</param>
  52. /// <returns>None : No Current CurrentLicense,FailAndExceedMaxAccountCount: CurrentLicense.MaxAccountCount> accountCount,Successd: accountCount>_currentLicense.MaxAccountCount</returns>
  53. public VerifyResult VerifyAccountCount(int accountCount)
  54. {
  55. if (_currentLicense == null)
  56. {
  57. return VerifyResult.None;
  58. }
  59. return _currentLicense.MaxAccountCount > accountCount ? VerifyResult.Succeeded : VerifyResult.FailAndExceedMaxAccountCount;
  60. }
  61. /// <summary>
  62. ///Gets VerifyResult when Verify current dateTime
  63. /// </summary>
  64. /// <param name="utcdateTime">UTC DateTime </param>
  65. /// <returns>None : No Current CurrentLicense,FailAndExceedExpirationDate: CurrentLicense.ExpirationUtcDate> utcdateTime,Successd: utcdateTime>_currentLicense.ExpirationUtcDate</returns>
  66. public VerifyResult VerifyExceedExpirationDate(DateTime dateTime)
  67. {
  68. if (_currentLicense == null)
  69. {
  70. return VerifyResult.None;
  71. }
  72. return (_currentLicense.ExpirationUtcDate - dateTime).TotalMinutes <= 0 ? VerifyResult.FailAndExceedExpirationDate : VerifyResult.Succeeded;
  73. }
  74. /// <summary>
  75. /// Gets Verify License Result when Load License File and Verify License
  76. /// </summary>
  77. /// <param name="currentDirectoryAbsolutePath">currrent Absolute server Directory Path</param>
  78. /// <param name="verifyResultinfo"> return verify License Result info</param>
  79. /// <returns>Verify Result(enum)</returns>
  80. public VerifyResult LoadLicenseFile(string currentDirectoryAbsolutePath, out string verifyResultinfo)
  81. {
  82. var licfiles = Directory.GetFiles(currentDirectoryAbsolutePath, "*.lic").OrderByDescending(x => new FileInfo(x).LastWriteTimeUtc).ToArray();
  83. string licfilePah = string.Empty;
  84. string stlicfilePah = Path.Combine(currentDirectoryAbsolutePath, startupFileName);
  85. if (licfiles.Length >= 1)
  86. {
  87. licfilePah = licfiles[0];
  88. }
  89. return VerifyLicenseFile(licfilePah, out verifyResultinfo, stlicfilePah, false);
  90. }
  91. public DateTime GetSystemFirstStartupTime(string currentDirectoryAbsolutePath)
  92. {
  93. string stlicfilePah = Path.Combine(currentDirectoryAbsolutePath, startupFileName);
  94. if (File.Exists(stlicfilePah))
  95. {
  96. var fileInfo = new FileInfo(stlicfilePah);
  97. return fileInfo.CreationTime;
  98. }
  99. else {
  100. return DateTime.UtcNow;
  101. }
  102. }
  103. /// <summary>
  104. /// Gets Verify Result when Verify License
  105. /// </summary>
  106. /// <param name="licenseAbsolutePath">license Absolute path</param>
  107. /// <param name="verifyResultinfo">return verify Lincese Result info </param>
  108. /// <param name="startupFileAbsolutePath"> first start up File Absolute Path</param>
  109. /// <param name="verifyOnly"> is or no only verify</param>
  110. /// <returns>VerifyResult</returns>
  111. public VerifyResult VerifyLicenseFile(string licenseAbsolutePath, out string verifyResultinfo, string startupFileAbsolutePath = null, bool verifyOnly = true)
  112. {
  113. var verifty = VerifyResult.Failed;
  114. try
  115. {
  116. if (!verifyOnly)
  117. {
  118. LoadStartupLicnese(startupFileAbsolutePath);
  119. }
  120. CurrentLicense = GetLicensefromFilePath(licenseAbsolutePath);
  121. if (CurrentLicense != null)
  122. {
  123. return GetVerifyResult(out verifyResultinfo, verifyOnly);
  124. }
  125. }
  126. catch (Exception e)
  127. {
  128. verifyResultinfo = $"VerifyLicnese:{verifty}\r\nLoad CurrentLicense Error:{e.StackTrace}";
  129. return verifty;
  130. }
  131. verifyResultinfo = $"VerifyLicnese:{verifty}";
  132. return verifty;
  133. }
  134. /// <summary>
  135. /// Gets a value that current expiration days
  136. /// </summary>
  137. /// <param name="currentUTCDateTime">current UTC DateTime</param>
  138. /// <returns></returns>
  139. private int GetCurrentExpirationDays(DateTime currentUTCDateTime)
  140. {
  141. if (_currentLicense != null) return (_currentLicense.ExpirationUtcDate - currentUTCDateTime).Days;
  142. return 0;
  143. }
  144. private VerifyResult GetVerifyResult(out string verifyResultinfo, bool verifyOnly)
  145. {
  146. var verifty = VerifyResult.Succeeded;
  147. verifyResultinfo = string.Empty;
  148. if (!verifyOnly && StartupLicnese != null)
  149. {
  150. if (CurrentLicense.LicenseType == LicenseType.Trial && CurrentLicense.ExpirationDay > 0)
  151. {
  152. CurrentLicense.ExpirationUtcDate = StartupLicnese.FirstStartupUtcDate.AddDays(CurrentLicense.ExpirationDay);
  153. }
  154. var veriftyDate = VerifyExceedExpirationDate(DateTime.Now);
  155. var verifyLocalInfo = VerifyLocalInfo(CurrentLicense.Identification);
  156. if (veriftyDate == VerifyResult.Succeeded)
  157. {
  158. if (verifyLocalInfo == VerifyResult.Succeeded)
  159. verifty = VerifyResult.Succeeded;
  160. else
  161. verifty = VerifyResult.FailAndExceedLocalInfo;
  162. }
  163. else
  164. {
  165. if (verifyLocalInfo == VerifyResult.Succeeded)
  166. verifty = VerifyResult.FailAndExceedExpirationDate;
  167. else
  168. verifty = VerifyResult.Failed;
  169. }
  170. if (verifty == VerifyResult.Succeeded)
  171. {
  172. verifyResultinfo = $"{ CurrentLicense.LicenseType.ToString()} period is running." + verifyResultinfo;
  173. StartTimer();
  174. }
  175. verifyResultinfo = $"{GetCurrentExpirationDays(DateTime.Now)} days left and " +
  176. $"expired by {CurrentLicense.ExpirationUtcDate}. " +
  177. $"it supports {CurrentLicense.MaxAccountCount} FLYINSONO client accounts and {CurrentLicense.MaxUsCount} ultrasonic machines.";
  178. if (!string.IsNullOrEmpty(CurrentLicense.Identification))
  179. verifyResultinfo += $"Identification:{CurrentLicense.Identification}";
  180. }
  181. return verifty;
  182. }
  183. /// <summary>
  184. /// Gets License from license Absolute path
  185. /// </summary>
  186. /// <param name="licenseAbsolutepath">license Absolute path</param>
  187. private License GetLicensefromFilePath(string licenseAbsolutepath)
  188. {
  189. if (File.Exists(licenseAbsolutepath))
  190. {
  191. var text = File.ReadAllText(licenseAbsolutepath);
  192. var decrypttext = AesHelper.Decrypt(text);
  193. var licnese = LicenseFileHelper.FromFile(decrypttext);
  194. return licnese;
  195. }
  196. return new License()
  197. {
  198. LicenseType = LicenseType.Trial,
  199. Version = CurrentVersion,
  200. LicenseId = Guid.NewGuid().ToString(),
  201. MaxAccountCount = 15,
  202. MaxUsCount = 15,
  203. ExpirationDay = 15,
  204. Remarks = "Default Trial License"
  205. };
  206. }
  207. /// <summary>
  208. /// Load Start up Licnese File or Create StartupLicnese and save File
  209. /// </summary>
  210. /// <param name="startupFileAbsolutePath">Absolute Path</param>
  211. private void LoadStartupLicnese(string startupFileAbsolutePath)
  212. {
  213. if (startupFileAbsolutePath != null && File.Exists(startupFileAbsolutePath))
  214. {
  215. var text = File.ReadAllText(startupFileAbsolutePath);
  216. var decrypttext = AesHelper.Decrypt(text);
  217. StartupLicnese = LicenseFileHelper.StartupLicneseFromFile(decrypttext);
  218. }
  219. else
  220. {
  221. StartupLicnese = new StartupLicnese
  222. {
  223. FirstStartupUtcDate = DateTime.UtcNow
  224. };
  225. var xml = LicenseFileHelper.StartupLicneseToFile(StartupLicnese);
  226. var encryptxml = AesHelper.Encrypt(xml);
  227. File.WriteAllText(startupFileAbsolutePath ?? throw new ArgumentNullException(nameof(startupFileAbsolutePath)), encryptxml);
  228. }
  229. }
  230. /// <summary>
  231. /// Export License and Save File
  232. /// </summary>
  233. /// <param name="license">license</param>
  234. /// <param name="path">Save File Path</param>
  235. /// <returns> is or no export successed</returns>
  236. public bool ExportLicenseFile(License license, string path, Stream userToolStream)
  237. {
  238. try
  239. {
  240. var xml = LicenseFileHelper.LinceseToFile(license);
  241. var encryptxml = AesHelper.Encrypt(xml);
  242. var launcher = path + "\\License loading tool.exe";
  243. using (userToolStream)
  244. {
  245. using (var launcherStream = File.Create(launcher))
  246. {
  247. userToolStream.CopyTo(launcherStream);
  248. }
  249. }
  250. using (var fs = new FileStream(launcher, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
  251. {
  252. using (var br = new BinaryWriter(fs))
  253. {
  254. fs.Position = fs.Length;
  255. var startPosition = (int)fs.Position;
  256. var data = Encoding.UTF8.GetBytes(encryptxml);
  257. br.Write(data);
  258. br.Write(startPosition);
  259. br.Write(data.Length);
  260. }
  261. }
  262. return true;
  263. }
  264. catch (Exception e)
  265. {
  266. throw new Exception("Export Error", e);
  267. }
  268. }
  269. public DateTime GetLocalFirstStartupDateTime()
  270. {
  271. return StartupLicnese?.FirstStartupUtcDate.ToLocalTime() ?? DateTime.MinValue;
  272. }
  273. /// <summary>
  274. ///Gets VerifyResult when Verify current Local Infomation
  275. /// </summary>
  276. /// <param name="utcdateTime">UTC DateTime </param>
  277. /// <returns>None : No Current CurrentLicense,FailAndExceedExpirationDate: CurrentLicense.ExpirationUtcDate> utcdateTime,Successd: utcdateTime>_currentLicense.ExpirationUtcDate</returns>
  278. public VerifyResult VerifyLocalInfo(string id)
  279. {
  280. if (_currentLicense == null)
  281. {
  282. return VerifyResult.None;
  283. }
  284. if (string.IsNullOrEmpty(id))
  285. return VerifyResult.Succeeded;
  286. id = id.Replace("-", "");
  287. var mac = GetLocalInfo.GetMacAddress();
  288. if (mac.Contains(id))
  289. {
  290. return VerifyResult.Succeeded;
  291. }
  292. else
  293. {
  294. return VerifyResult.Failed;
  295. }
  296. }
  297. #endregion
  298. #region Check Current License Timer
  299. private System.Threading.Timer _verifyTimer;
  300. /// <summary>
  301. /// one Day Check License
  302. /// </summary>
  303. private const int TntervalDay = 1;
  304. /// <summary>
  305. /// Notify Expiration Datetime event
  306. /// </summary>
  307. public event EventHandler<LicenseExpirationInfo> NotifyLicenseExpirationEvent;
  308. private void StartTimer()
  309. {
  310. _verifyTimer = new System.Threading.Timer(CheckLicenseTimeTick, null, 1000 * 60 * 60 * 6 * TntervalDay, 1000 * 60 * 60 * 6 * TntervalDay);
  311. }
  312. void CheckLicenseTimeTick(object o)
  313. {
  314. if (CurrentLicense == null) return;
  315. var localTime = CurrentLicense.ExpirationUtcDate.ToLocalTime();
  316. NotifyLicenseExpirationEvent?.Invoke(this, new LicenseExpirationInfo()
  317. {
  318. AvailableDays = GetCurrentExpirationDays(DateTime.UtcNow) + 1,
  319. LocalExpirationDate = localTime,
  320. HasExpired = (localTime - DateTime.Now).Minutes < 0,
  321. });
  322. }
  323. public void Dispose()
  324. {
  325. _verifyTimer?.Dispose();
  326. }
  327. #endregion
  328. }
  329. }