| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 | 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(_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;        }    }}
 |