MBLicenseFile.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using MediaBrowser.Common.Configuration;
  9. using MediaBrowser.Model.Cryptography;
  10. using MediaBrowser.Model.IO;
  11. namespace Emby.Server.Implementations.Security
  12. {
  13. internal class MBLicenseFile
  14. {
  15. private readonly IApplicationPaths _appPaths;
  16. private readonly IFileSystem _fileSystem;
  17. private readonly ICryptoProvider _cryptographyProvider;
  18. public string RegKey
  19. {
  20. get => _regKey;
  21. set
  22. {
  23. _updateRecords.Clear();
  24. _regKey = value;
  25. }
  26. }
  27. private string Filename => Path.Combine(_appPaths.ConfigurationDirectoryPath, "mb.lic");
  28. private readonly ConcurrentDictionary<Guid, FeatureRegInfo> _updateRecords = new ConcurrentDictionary<Guid, FeatureRegInfo>();
  29. private readonly object _fileLock = new object();
  30. private string _regKey;
  31. public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
  32. {
  33. _appPaths = appPaths;
  34. _fileSystem = fileSystem;
  35. _cryptographyProvider = cryptographyProvider;
  36. Load();
  37. }
  38. private void SetUpdateRecord(Guid key, FeatureRegInfo value)
  39. {
  40. _updateRecords.AddOrUpdate(key, value, (k, v) => value);
  41. }
  42. private Guid GetKey(string featureId)
  43. {
  44. return new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId)));
  45. }
  46. public void AddRegCheck(string featureId, DateTime expirationDate)
  47. {
  48. var key = GetKey(featureId);
  49. var value = new FeatureRegInfo
  50. {
  51. ExpirationDate = expirationDate,
  52. LastChecked = DateTime.UtcNow
  53. };
  54. SetUpdateRecord(key, value);
  55. Save();
  56. }
  57. public void RemoveRegCheck(string featureId)
  58. {
  59. var key = GetKey(featureId);
  60. _updateRecords.TryRemove(key, out var val);
  61. Save();
  62. }
  63. public FeatureRegInfo GetRegInfo(string featureId)
  64. {
  65. var key = GetKey(featureId);
  66. FeatureRegInfo info = null;
  67. _updateRecords.TryGetValue(key, out info);
  68. if (info == null)
  69. {
  70. return null;
  71. }
  72. // guard agains people just putting a large number in the file
  73. return info.LastChecked < DateTime.UtcNow ? info : null;
  74. }
  75. private void Load()
  76. {
  77. string[] contents = null;
  78. var licenseFile = Filename;
  79. lock (_fileLock)
  80. {
  81. try
  82. {
  83. contents = _fileSystem.ReadAllLines(licenseFile);
  84. }
  85. catch (FileNotFoundException)
  86. {
  87. lock (_fileLock)
  88. {
  89. _fileSystem.WriteAllBytes(licenseFile, Array.Empty<byte>());
  90. }
  91. }
  92. catch (IOException)
  93. {
  94. lock (_fileLock)
  95. {
  96. _fileSystem.WriteAllBytes(licenseFile, Array.Empty<byte>());
  97. }
  98. }
  99. }
  100. if (contents != null && contents.Length > 0)
  101. {
  102. //first line is reg key
  103. RegKey = contents[0];
  104. //next is legacy key
  105. if (contents.Length > 1)
  106. {
  107. // Don't need this anymore
  108. }
  109. //the rest of the lines should be pairs of features and timestamps
  110. for (var i = 2; i < contents.Length; i = i + 2)
  111. {
  112. var line = contents[i];
  113. if (string.IsNullOrWhiteSpace(line))
  114. {
  115. continue;
  116. }
  117. if (Guid.TryParse(line, out var feat))
  118. {
  119. var lineParts = contents[i + 1].Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
  120. if (long.TryParse(lineParts[0], out var ticks))
  121. {
  122. var info = new FeatureRegInfo
  123. {
  124. LastChecked = new DateTime(ticks)
  125. };
  126. if (lineParts.Length > 1 && long.TryParse(lineParts[1], out ticks))
  127. {
  128. info.ExpirationDate = new DateTime(ticks);
  129. }
  130. SetUpdateRecord(feat, info);
  131. }
  132. }
  133. }
  134. }
  135. }
  136. public void Save()
  137. {
  138. //build our array
  139. var lines = new List<string>
  140. {
  141. RegKey,
  142. // Legacy key
  143. string.Empty
  144. };
  145. foreach (var pair in _updateRecords
  146. .ToList())
  147. {
  148. lines.Add(pair.Key.ToString());
  149. var dateLine = pair.Value.LastChecked.Ticks.ToString(CultureInfo.InvariantCulture) + "|" +
  150. pair.Value.ExpirationDate.Ticks.ToString(CultureInfo.InvariantCulture);
  151. lines.Add(dateLine);
  152. }
  153. var licenseFile = Filename;
  154. _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(licenseFile));
  155. lock (_fileLock)
  156. {
  157. _fileSystem.WriteAllLines(licenseFile, lines);
  158. }
  159. }
  160. }
  161. internal class FeatureRegInfo
  162. {
  163. public DateTime ExpirationDate { get; set; }
  164. public DateTime LastChecked { get; set; }
  165. public FeatureRegInfo()
  166. {
  167. ExpirationDate = DateTime.MinValue;
  168. }
  169. }
  170. }