aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
blob: 79e558794f8c4a24c3f3122b3f51588d25727f86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
using MediaBrowser.Common.Configuration;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace MediaBrowser.Common.Implementations.Security
{
    internal class MBLicenseFile
    {
        private readonly IApplicationPaths _appPaths;

        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, DateTime> _updateRecords = new ConcurrentDictionary<Guid, DateTime>();
        private readonly object _fileLock = new object();
        private string _regKey;

        public MBLicenseFile(IApplicationPaths appPaths)
        {
            _appPaths = appPaths;

            Load();
        }

        private void SetUpdateRecord(Guid key, DateTime value)
        {
            _updateRecords.AddOrUpdate(key, value, (k, v) => value);
        }

        public void AddRegCheck(string featureId)
        {
            using (var provider = new MD5CryptoServiceProvider())
            {
                var key = new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId)));
                var value = DateTime.UtcNow;

                SetUpdateRecord(key, value);
                Save();
            }

        }

        public void RemoveRegCheck(string featureId)
        {
            using (var provider = new MD5CryptoServiceProvider())
            {
                var key = new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId)));
                DateTime val;

                _updateRecords.TryRemove(key, out val);

                Save();
            }

        }

        public DateTime LastChecked(string featureId)
        {
            using (var provider = new MD5CryptoServiceProvider())
            {
                DateTime last;
                _updateRecords.TryGetValue(new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId))), out last);

                // guard agains people just putting a large number in the file
                return last < DateTime.UtcNow ? last : DateTime.MinValue;  
            }
        }

        private void Load()
        {
            string[] contents = null;
            var licenseFile = Filename;
            lock (_fileLock)
            {
                try
                {
					contents = File.ReadAllLines(licenseFile);
                }
                catch (DirectoryNotFoundException)
                {
                    (File.Create(licenseFile)).Close();
                }
                catch (FileNotFoundException)
                {
					(File.Create(licenseFile)).Close();
                }
            }
            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 feat = Guid.Parse(contents[i]);

                    SetUpdateRecord(feat, new DateTime(Convert.ToInt64(contents[i + 1])));
                }
            }
        }

        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());
                lines.Add(pair.Value.Ticks.ToString(CultureInfo.InvariantCulture));
            }

            var licenseFile = Filename;
			Directory.CreateDirectory(Path.GetDirectoryName(licenseFile));
			lock (_fileLock) File.WriteAllLines(licenseFile, lines);
        }
    }
}