ec1f5dc317
Add Argument*Exceptions now use proper nameof operators. Added exception messages to quite a few Argument*Exceptions. Fixed rethorwing to be proper syntax. Added a ton of null checkes. (This is only a start, there are about 500 places that need proper null handling) Added some TODOs to log certain exceptions. Fix sln again. Fixed all AssemblyInfo's and added proper copyright (where I could find them) We live in *current year*. Fixed the use of braces. Fixed a ton of properties, and made a fair amount of functions static that should be and can be static. Made more Methods that should be static static. You can now use static to find bad functions! Removed unused variable. And added one more proper XML comment.
205 lines
6.1 KiB
C#
205 lines
6.1 KiB
C#
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 => _regKey;
|
|
set
|
|
{
|
|
_updateRecords.Clear();
|
|
_regKey = value;
|
|
}
|
|
}
|
|
|
|
private string Filename => 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, Array.Empty<byte>());
|
|
}
|
|
}
|
|
catch (IOException)
|
|
{
|
|
lock (_fileLock)
|
|
{
|
|
_fileSystem.WriteAllBytes(licenseFile, Array.Empty<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(_fileSystem.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;
|
|
}
|
|
}
|
|
}
|