aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Security/MBLicenseFile.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Security/MBLicenseFile.cs')
-rw-r--r--Emby.Server.Implementations/Security/MBLicenseFile.cs214
1 files changed, 214 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Security/MBLicenseFile.cs b/Emby.Server.Implementations/Security/MBLicenseFile.cs
new file mode 100644
index 000000000..c791d6a52
--- /dev/null
+++ b/Emby.Server.Implementations/Security/MBLicenseFile.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.IO;
+
+namespace Emby.Server.Implementations.Security
+{
+ internal class MBLicenseFile
+ {
+ private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
+ private readonly ICryptoProvider _cryptographyProvider;
+
+ public string RegKey
+ {
+ get { return _regKey; }
+ set
+ {
+ if (value != _regKey)
+ {
+ //if key is changed - clear out our saved validations
+ _updateRecords.Clear();
+ _regKey = value;
+ }
+ }
+ }
+
+ private string Filename
+ {
+ get
+ {
+ return Path.Combine(_appPaths.ConfigurationDirectoryPath, "mb.lic");
+ }
+ }
+
+ private readonly ConcurrentDictionary<Guid, FeatureRegInfo> _updateRecords = new ConcurrentDictionary<Guid, FeatureRegInfo>();
+ private readonly object _fileLock = new object();
+ private string _regKey;
+
+ public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
+ {
+ _appPaths = appPaths;
+ _fileSystem = fileSystem;
+ _cryptographyProvider = cryptographyProvider;
+
+ Load();
+ }
+
+ private void SetUpdateRecord(Guid key, FeatureRegInfo value)
+ {
+ _updateRecords.AddOrUpdate(key, value, (k, v) => value);
+ }
+
+ private Guid GetKey(string featureId)
+ {
+ return new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId)));
+ }
+
+ public void AddRegCheck(string featureId, DateTime expirationDate)
+ {
+ var key = GetKey(featureId);
+ var value = new FeatureRegInfo
+ {
+ ExpirationDate = expirationDate,
+ LastChecked = DateTime.UtcNow
+ };
+
+ SetUpdateRecord(key, value);
+ Save();
+ }
+
+ public void RemoveRegCheck(string featureId)
+ {
+ var key = GetKey(featureId);
+ FeatureRegInfo val;
+
+ _updateRecords.TryRemove(key, out val);
+
+ Save();
+ }
+
+ public FeatureRegInfo GetRegInfo(string featureId)
+ {
+ var key = GetKey(featureId);
+ FeatureRegInfo info = null;
+ _updateRecords.TryGetValue(key, out info);
+
+ if (info == null)
+ {
+ return null;
+ }
+
+ // guard agains people just putting a large number in the file
+ return info.LastChecked < DateTime.UtcNow ? info : null;
+ }
+
+ private void Load()
+ {
+ string[] contents = null;
+ var licenseFile = Filename;
+ lock (_fileLock)
+ {
+ try
+ {
+ contents = _fileSystem.ReadAllLines(licenseFile);
+ }
+ catch (FileNotFoundException)
+ {
+ lock (_fileLock)
+ {
+ _fileSystem.WriteAllBytes(licenseFile, new byte[] { });
+ }
+ }
+ catch (IOException)
+ {
+ lock (_fileLock)
+ {
+ _fileSystem.WriteAllBytes(licenseFile, new byte[] { });
+ }
+ }
+ }
+ if (contents != null && contents.Length > 0)
+ {
+ //first line is reg key
+ RegKey = contents[0];
+
+ //next is legacy key
+ if (contents.Length > 1)
+ {
+ // Don't need this anymore
+ }
+
+ //the rest of the lines should be pairs of features and timestamps
+ for (var i = 2; i < contents.Length; i = i + 2)
+ {
+ var line = contents[i];
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ continue;
+ }
+
+ Guid feat;
+ if (Guid.TryParse(line, out feat))
+ {
+ var lineParts = contents[i + 1].Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+
+ long ticks;
+ if (long.TryParse(lineParts[0], out ticks))
+ {
+ var info = new FeatureRegInfo
+ {
+ LastChecked = new DateTime(ticks)
+ };
+
+ if (lineParts.Length > 1 && long.TryParse(lineParts[1], out ticks))
+ {
+ info.ExpirationDate = new DateTime(ticks);
+ }
+
+ SetUpdateRecord(feat, info);
+ }
+ }
+ }
+ }
+ }
+
+ public void Save()
+ {
+ //build our array
+ var lines = new List<string>
+ {
+ RegKey,
+
+ // Legacy key
+ string.Empty
+ };
+
+ foreach (var pair in _updateRecords
+ .ToList())
+ {
+ lines.Add(pair.Key.ToString());
+
+ var dateLine = pair.Value.LastChecked.Ticks.ToString(CultureInfo.InvariantCulture) + "|" +
+ pair.Value.ExpirationDate.Ticks.ToString(CultureInfo.InvariantCulture);
+
+ lines.Add(dateLine);
+ }
+
+ var licenseFile = Filename;
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile));
+ lock (_fileLock)
+ {
+ _fileSystem.WriteAllLines(licenseFile, lines);
+ }
+ }
+ }
+
+ internal class FeatureRegInfo
+ {
+ public DateTime ExpirationDate { get; set; }
+ public DateTime LastChecked { get; set; }
+
+ public FeatureRegInfo()
+ {
+ ExpirationDate = DateTime.MinValue;
+ }
+ }
+}