mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			211 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			6.2 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 { return _regKey; }
 | 
						|
            set
 | 
						|
            {
 | 
						|
                _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, 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;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |