aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Common.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Common.Implementations')
-rw-r--r--MediaBrowser.Common.Implementations/BaseApplicationHost.cs26
-rw-r--r--MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs12
-rw-r--r--MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs9
-rw-r--r--MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs11
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj6
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs8
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs8
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs8
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs17
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs2
-rw-r--r--MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs157
-rw-r--r--MediaBrowser.Common.Implementations/Security/MbAdmin.cs13
-rw-r--r--MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs337
-rw-r--r--MediaBrowser.Common.Implementations/Security/RegRecord.cs12
-rw-r--r--MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs14
-rw-r--r--MediaBrowser.Common.Implementations/Updates/InstallationManager.cs686
16 files changed, 48 insertions, 1278 deletions
diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
index 4b9d78c9ca..ec96818aa6 100644
--- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
+++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Common.Events;
using MediaBrowser.Common.Implementations.Devices;
using MediaBrowser.Common.Implementations.IO;
using MediaBrowser.Common.Implementations.ScheduledTasks;
-using MediaBrowser.Common.Implementations.Security;
using MediaBrowser.Common.Implementations.Serialization;
using MediaBrowser.Common.Implementations.Updates;
using MediaBrowser.Common.Net;
@@ -31,6 +30,7 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Implementations.Cryptography;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.System;
using MediaBrowser.Model.Tasks;
namespace MediaBrowser.Common.Implementations
@@ -121,11 +121,6 @@ namespace MediaBrowser.Common.Implementations
/// <value>The kernel.</value>
protected ITaskManager TaskManager { get; private set; }
/// <summary>
- /// Gets the security manager.
- /// </summary>
- /// <value>The security manager.</value>
- protected ISecurityManager SecurityManager { get; private set; }
- /// <summary>
/// Gets the HTTP client.
/// </summary>
/// <value>The HTTP client.</value>
@@ -142,16 +137,12 @@ namespace MediaBrowser.Common.Implementations
/// <value>The configuration manager.</value>
protected IConfigurationManager ConfigurationManager { get; private set; }
- /// <summary>
- /// Gets or sets the installation manager.
- /// </summary>
- /// <value>The installation manager.</value>
- protected IInstallationManager InstallationManager { get; private set; }
-
protected IFileSystem FileSystemManager { get; private set; }
protected IIsoManager IsoManager { get; private set; }
+ protected ISystemEvents SystemEvents { get; private set; }
+
/// <summary>
/// Gets the name.
/// </summary>
@@ -221,6 +212,7 @@ namespace MediaBrowser.Common.Implementations
JsonSerializer = CreateJsonSerializer();
MemoryStreamProvider = CreateMemoryStreamProvider();
+ SystemEvents = CreateSystemEvents();
OnLoggerLoaded(true);
LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
@@ -254,6 +246,7 @@ namespace MediaBrowser.Common.Implementations
}
protected abstract IMemoryStreamProvider CreateMemoryStreamProvider();
+ protected abstract ISystemEvents CreateSystemEvents();
protected virtual void OnLoggerLoaded(bool isFirstLoad)
{
@@ -473,11 +466,12 @@ namespace MediaBrowser.Common.Implementations
RegisterSingleInstance<IApplicationPaths>(ApplicationPaths);
- TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LogManager.GetLogger("TaskManager"), FileSystemManager);
+ TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LogManager.GetLogger("TaskManager"), FileSystemManager, SystemEvents);
RegisterSingleInstance(JsonSerializer);
RegisterSingleInstance(XmlSerializer);
RegisterSingleInstance(MemoryStreamProvider);
+ RegisterSingleInstance(SystemEvents);
RegisterSingleInstance(LogManager);
RegisterSingleInstance(Logger);
@@ -492,12 +486,6 @@ namespace MediaBrowser.Common.Implementations
NetworkManager = CreateNetworkManager(LogManager.GetLogger("NetworkManager"));
RegisterSingleInstance(NetworkManager);
- SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager);
- RegisterSingleInstance(SecurityManager);
-
- InstallationManager = new InstallationManager(LogManager.GetLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager);
- RegisterSingleInstance(InstallationManager);
-
IsoManager = new IsoManager();
RegisterSingleInstance(IsoManager);
diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
index 7c1302ff65..943e6c5f88 100644
--- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
+++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
@@ -79,7 +79,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
get
{
// Lazy load
- LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer));
+ LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer, FileSystem));
return _configuration;
}
protected set
@@ -126,7 +126,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
Logger.Info("Saving system configuration");
var path = CommonApplicationPaths.SystemConfigurationFilePath;
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_configurationSyncLock)
{
@@ -196,9 +196,9 @@ namespace MediaBrowser.Common.Implementations.Configuration
&& !string.Equals(CommonConfiguration.CachePath ?? string.Empty, newPath))
{
// Validate
- if (!Directory.Exists(newPath))
+ if (!FileSystem.DirectoryExists(newPath))
{
- throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
+ throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
}
EnsureWriteAccess(newPath);
@@ -253,7 +253,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
{
return Activator.CreateInstance(configurationType);
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
return Activator.CreateInstance(configurationType);
}
@@ -293,7 +293,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
_configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
var path = GetConfigurationFile(key);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_configurationSyncLock)
{
diff --git a/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
index 419b85fa73..0c1683f93e 100644
--- a/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
+++ b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
@@ -2,6 +2,7 @@
using System;
using System.IO;
using System.Linq;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Common.Implementations.Configuration
{
@@ -18,7 +19,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
/// <param name="path">The path.</param>
/// <param name="xmlSerializer">The XML serializer.</param>
/// <returns>System.Object.</returns>
- public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer)
+ public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
{
object configuration;
@@ -27,7 +28,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
// Use try/catch to avoid the extra file system lookup using File.Exists
try
{
- buffer = File.ReadAllBytes(path);
+ buffer = fileSystem.ReadAllBytes(path);
configuration = xmlSerializer.DeserializeFromBytes(type, buffer);
}
@@ -46,10 +47,10 @@ namespace MediaBrowser.Common.Implementations.Configuration
// If the file didn't exist before, or if something has changed, re-save
if (buffer == null || !buffer.SequenceEqual(newBytes))
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ fileSystem.CreateDirectory(Path.GetDirectoryName(path));
// Save it after load in case we got new items
- File.WriteAllBytes(path, newBytes);
+ fileSystem.WriteAllBytes(path, newBytes);
}
return configuration;
diff --git a/MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs b/MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs
index 8b027d41ac..4f6c34cb7b 100644
--- a/MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs
+++ b/MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
-using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
@@ -660,6 +659,11 @@ namespace MediaBrowser.Common.Implementations.IO
return File.ReadAllText(path);
}
+ public byte[] ReadAllBytes(string path)
+ {
+ return File.ReadAllBytes(path);
+ }
+
public void WriteAllText(string path, string text, Encoding encoding)
{
File.WriteAllText(path, text, encoding);
@@ -670,6 +674,11 @@ namespace MediaBrowser.Common.Implementations.IO
File.WriteAllText(path, text);
}
+ public void WriteAllBytes(string path, byte[] bytes)
+ {
+ File.WriteAllBytes(path, bytes);
+ }
+
public string ReadAllText(string path, Encoding encoding)
{
return File.ReadAllText(path, encoding);
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index 4b3fe3dba9..89e9427ae4 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -79,14 +79,8 @@
<Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\ReloadLoggerFileTask.cs" />
<Compile Include="ScheduledTasks\WeeklyTrigger.cs" />
- <Compile Include="Security\MbAdmin.cs" />
- <Compile Include="Security\MBLicenseFile.cs" />
- <Compile Include="Security\PluginSecurityManager.cs" />
- <Compile Include="Security\RegRecord.cs" />
- <Compile Include="Security\SuppporterInfoResponse.cs" />
<Compile Include="Serialization\XmlSerializer.cs" />
<Compile Include="Updates\GithubUpdater.cs" />
- <Compile Include="Updates\InstallationManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs
index 3d33e958de..ab1d8f02dc 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs
@@ -1,11 +1,11 @@
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
-using System;
+using System;
using System.Globalization;
using System.Threading;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
/// <summary>
/// Represents a task trigger that fires everyday
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs
index 8038d5551d..251e460cb1 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs
@@ -1,11 +1,11 @@
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
-using System;
+using System;
using System.Linq;
using System.Threading;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
/// <summary>
/// Represents a task trigger that runs repeatedly on an interval
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs
index 41f58a7ad5..c96a41ac80 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs
@@ -1,10 +1,10 @@
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
-using System;
+using System;
using System.Threading.Tasks;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
/// <summary>
/// Class StartupTaskTrigger
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
index 9a0221deab..5c721d915e 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
@@ -12,6 +12,7 @@ using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.System;
using Microsoft.Win32;
namespace MediaBrowser.Common.Implementations.ScheduledTasks
@@ -48,6 +49,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <value>The application paths.</value>
private IApplicationPaths ApplicationPaths { get; set; }
+ private readonly ISystemEvents _systemEvents;
+
/// <summary>
/// Gets the logger.
/// </summary>
@@ -81,29 +84,23 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logger">The logger.</param>
/// <exception cref="System.ArgumentException">kernel</exception>
- public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem)
+ public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem, ISystemEvents systemEvents)
{
ApplicationPaths = applicationPaths;
JsonSerializer = jsonSerializer;
Logger = logger;
_fileSystem = fileSystem;
+ _systemEvents = systemEvents;
ScheduledTasks = new IScheduledTaskWorker[] { };
}
private void BindToSystemEvent()
{
- try
- {
- SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
- }
- catch
- {
-
- }
+ _systemEvents.Resume += _systemEvents_Resume;
}
- void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
+ private void _systemEvents_Resume(object sender, EventArgs e)
{
foreach (var task in ScheduledTasks)
{
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs
index 318802e07d..0d8af4e9c2 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs
@@ -4,7 +4,7 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
/// <summary>
/// Represents a task trigger that fires on a weekly basis
diff --git a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
deleted file mode 100644
index 78515cd141..0000000000
--- a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-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);
- }
- }
-}
diff --git a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs
deleted file mode 100644
index 76ff92c2eb..0000000000
--- a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-
-namespace MediaBrowser.Common.Implementations.Security
-{
- public class MbAdmin
- {
- public const string HttpUrl = "https://www.mb3admin.com/admin/";
-
- /// <summary>
- /// Leaving as http for now until we get it squared away
- /// </summary>
- public const string HttpsUrl = "https://www.mb3admin.com/admin/";
- }
-}
diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs
deleted file mode 100644
index 5d440609ef..0000000000
--- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs
+++ /dev/null
@@ -1,337 +0,0 @@
-using System.IO;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Net;
-
-namespace MediaBrowser.Common.Implementations.Security
-{
- /// <summary>
- /// Class PluginSecurityManager
- /// </summary>
- public class PluginSecurityManager : ISecurityManager
- {
- private const string MBValidateUrl = MbAdmin.HttpsUrl + "service/registration/validate";
- private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "https://mb3admin.com/admin/service/appstore/register";
-
- /// <summary>
- /// The _is MB supporter
- /// </summary>
- private bool? _isMbSupporter;
- /// <summary>
- /// The _is MB supporter initialized
- /// </summary>
- private bool _isMbSupporterInitialized;
- /// <summary>
- /// The _is MB supporter sync lock
- /// </summary>
- private object _isMbSupporterSyncLock = new object();
-
- /// <summary>
- /// Gets a value indicating whether this instance is MB supporter.
- /// </summary>
- /// <value><c>true</c> if this instance is MB supporter; otherwise, <c>false</c>.</value>
- public bool IsMBSupporter
- {
- get
- {
- LazyInitializer.EnsureInitialized(ref _isMbSupporter, ref _isMbSupporterInitialized, ref _isMbSupporterSyncLock, () => GetSupporterRegistrationStatus().Result.IsRegistered);
- return _isMbSupporter.Value;
- }
- }
-
- private MBLicenseFile _licenseFile;
- private MBLicenseFile LicenseFile
- {
- get { return _licenseFile ?? (_licenseFile = new MBLicenseFile(_appPaths)); }
- }
-
- private readonly IHttpClient _httpClient;
- private readonly IJsonSerializer _jsonSerializer;
- private readonly IApplicationHost _appHost;
- private readonly ILogger _logger;
- private readonly IApplicationPaths _appPaths;
-
- private IEnumerable<IRequiresRegistration> _registeredEntities;
- protected IEnumerable<IRequiresRegistration> RegisteredEntities
- {
- get
- {
- return _registeredEntities ?? (_registeredEntities = _appHost.GetExports<IRequiresRegistration>());
- }
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="PluginSecurityManager" /> class.
- /// </summary>
- public PluginSecurityManager(IApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer,
- IApplicationPaths appPaths, ILogManager logManager)
- {
- if (httpClient == null)
- {
- throw new ArgumentNullException("httpClient");
- }
-
- _appHost = appHost;
- _httpClient = httpClient;
- _jsonSerializer = jsonSerializer;
- _appPaths = appPaths;
- _logger = logManager.GetLogger("SecurityManager");
- }
-
- /// <summary>
- /// Load all registration info for all entities that require registration
- /// </summary>
- /// <returns></returns>
- public async Task LoadAllRegistrationInfo()
- {
- var tasks = new List<Task>();
-
- ResetSupporterInfo();
- tasks.AddRange(RegisteredEntities.Select(i => i.LoadRegistrationInfoAsync()));
- await Task.WhenAll(tasks);
- }
-
- /// <summary>
- /// Gets the registration status.
- /// This overload supports existing plug-ins.
- /// </summary>
- /// <param name="feature">The feature.</param>
- /// <param name="mb2Equivalent">The MB2 equivalent.</param>
- /// <returns>Task{MBRegistrationRecord}.</returns>
- public Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent = null)
- {
- return GetRegistrationStatusInternal(feature, mb2Equivalent);
- }
-
- /// <summary>
- /// Gets the registration status.
- /// </summary>
- /// <param name="feature">The feature.</param>
- /// <param name="mb2Equivalent">The MB2 equivalent.</param>
- /// <param name="version">The version of this feature</param>
- /// <returns>Task{MBRegistrationRecord}.</returns>
- public Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent, string version)
- {
- return GetRegistrationStatusInternal(feature, mb2Equivalent, version);
- }
-
- private Task<MBRegistrationRecord> GetSupporterRegistrationStatus()
- {
- return GetRegistrationStatusInternal("MBSupporter", null, _appHost.ApplicationVersion.ToString());
- }
-
- /// <summary>
- /// Gets or sets the supporter key.
- /// </summary>
- /// <value>The supporter key.</value>
- public string SupporterKey
- {
- get
- {
- return LicenseFile.RegKey;
- }
- set
- {
- var newValue = value;
- if (newValue != null)
- {
- newValue = newValue.Trim();
- }
-
- if (newValue != LicenseFile.RegKey)
- {
- LicenseFile.RegKey = newValue;
- LicenseFile.Save();
-
- // re-load registration info
- Task.Run(() => LoadAllRegistrationInfo());
- }
- }
- }
-
- /// <summary>
- /// Register an app store sale with our back-end. It will validate the transaction with the store
- /// and then register the proper feature and then fill in the supporter key on success.
- /// </summary>
- /// <param name="parameters">Json parameters to send to admin server</param>
- public async Task RegisterAppStoreSale(string parameters)
- {
- var options = new HttpRequestOptions()
- {
- Url = AppstoreRegUrl,
- CancellationToken = CancellationToken.None,
- BufferContent = false
- };
- options.RequestHeaders.Add("X-Emby-Token", _appHost.SystemId);
- options.RequestContent = parameters;
- options.RequestContentType = "application/json";
-
- try
- {
- using (var response = await _httpClient.Post(options).ConfigureAwait(false))
- {
- var reg = _jsonSerializer.DeserializeFromStream<RegRecord>(response.Content);
-
- if (reg == null)
- {
- var msg = "Result from appstore registration was null.";
- _logger.Error(msg);
- throw new ApplicationException(msg);
- }
- if (!String.IsNullOrEmpty(reg.key))
- {
- SupporterKey = reg.key;
- }
- }
-
- }
- catch (ApplicationException)
- {
- SaveAppStoreInfo(parameters);
- throw;
- }
- catch (HttpException e)
- {
- _logger.ErrorException("Error registering appstore purchase {0}", e, parameters ?? "NO PARMS SENT");
-
- if (e.StatusCode.HasValue && e.StatusCode.Value == HttpStatusCode.PaymentRequired)
- {
- throw new PaymentRequiredException();
- }
- throw new ApplicationException("Error registering store sale");
- }
- catch (Exception e)
- {
- _logger.ErrorException("Error registering appstore purchase {0}", e, parameters ?? "NO PARMS SENT");
- SaveAppStoreInfo(parameters);
- //TODO - could create a re-try routine on start-up if this file is there. For now we can handle manually.
- throw new ApplicationException("Error registering store sale");
- }
-
- }
-
- private void SaveAppStoreInfo(string info)
- {
- // Save all transaction information to a file
-
- try
- {
- File.WriteAllText(Path.Combine(_appPaths.ProgramDataPath, "apptrans-error.txt"), info);
- }
- catch (IOException)
- {
-
- }
- }
-
- private async Task<MBRegistrationRecord> GetRegistrationStatusInternal(string feature,
- string mb2Equivalent = null,
- string version = null)
- {
- var lastChecked = LicenseFile.LastChecked(feature);
-
- //check the reg file first to alleviate strain on the MB admin server - must actually check in every 30 days tho
- var reg = new RegRecord
- {
- // Cache the result for up to a week
- registered = lastChecked > DateTime.UtcNow.AddDays(-7)
- };
-
- var success = reg.registered;
-
- if (!(lastChecked > DateTime.UtcNow.AddDays(-1)))
- {
- var data = new Dictionary<string, string>
- {
- { "feature", feature },
- { "key", SupporterKey },
- { "mac", _appHost.SystemId },
- { "systemid", _appHost.SystemId },
- { "mb2equiv", mb2Equivalent },
- { "ver", version },
- { "platform", _appHost.OperatingSystemDisplayName },
- { "isservice", _appHost.IsRunningAsService.ToString().ToLower() }
- };
-
- try
- {
- var options = new HttpRequestOptions
- {
- Url = MBValidateUrl,
-
- // Seeing block length errors
- EnableHttpCompression = false,
- BufferContent = false
- };
-
- options.SetPostData(data);
-
- using (var json = (await _httpClient.Post(options).ConfigureAwait(false)).Content)
- {
- reg = _jsonSerializer.DeserializeFromStream<RegRecord>(json);
- success = true;
- }
-
- if (reg.registered)
- {
- LicenseFile.AddRegCheck(feature);
- }
- else
- {
- LicenseFile.RemoveRegCheck(feature);
- }
-
- }
- catch (Exception e)
- {
- _logger.ErrorException("Error checking registration status of {0}", e, feature);
- }
- }
-
- var record = new MBRegistrationRecord
- {
- IsRegistered = reg.registered,
- ExpirationDate = reg.expDate,
- RegChecked = true,
- RegError = !success
- };
-
- record.TrialVersion = IsInTrial(reg.expDate, record.RegChecked, record.IsRegistered);
- record.IsValid = !record.RegChecked || record.IsRegistered || record.TrialVersion;
-
- return record;
- }
-
- private bool IsInTrial(DateTime expirationDate, bool regChecked, bool isRegistered)
- {
- //don't set this until we've successfully obtained exp date
- if (!regChecked)
- {
- return false;
- }
-
- var isInTrial = expirationDate > DateTime.UtcNow;
-
- return isInTrial && !isRegistered;
- }
-
- /// <summary>
- /// Resets the supporter info.
- /// </summary>
- private void ResetSupporterInfo()
- {
- _isMbSupporter = null;
- _isMbSupporterInitialized = false;
- }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Common.Implementations/Security/RegRecord.cs b/MediaBrowser.Common.Implementations/Security/RegRecord.cs
deleted file mode 100644
index ece70b7726..0000000000
--- a/MediaBrowser.Common.Implementations/Security/RegRecord.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-
-namespace MediaBrowser.Common.Implementations.Security
-{
- class RegRecord
- {
- public string featId { get; set; }
- public bool registered { get; set; }
- public DateTime expDate { get; set; }
- public string key { get; set; }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs b/MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs
deleted file mode 100644
index 49c5af8d82..0000000000
--- a/MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-
-namespace MediaBrowser.Common.Implementations.Security
-{
- internal class SuppporterInfoResponse
- {
- public string email { get; set; }
- public string supporterKey { get; set; }
- public int totalRegs { get; set; }
- public int totalMachines { get; set; }
- public string expDate { get; set; }
- public string regDate { get; set; }
- public string planType { get; set; }
- }
-}
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
deleted file mode 100644
index 934898f778..0000000000
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ /dev/null
@@ -1,686 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Implementations.Security;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Common.Progress;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Common.Updates;
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Updates;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Model.IO;
-
-namespace MediaBrowser.Common.Implementations.Updates
-{
- /// <summary>
- /// Manages all install, uninstall and update operations (both plugins and system)
- /// </summary>
- public class InstallationManager : IInstallationManager
- {
- public event EventHandler<InstallationEventArgs> PackageInstalling;
- public event EventHandler<InstallationEventArgs> PackageInstallationCompleted;
- public event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
- public event EventHandler<InstallationEventArgs> PackageInstallationCancelled;
-
- /// <summary>
- /// The current installations
- /// </summary>
- public List<Tuple<InstallationInfo, CancellationTokenSource>> CurrentInstallations { get; set; }
-
- /// <summary>
- /// The completed installations
- /// </summary>
- public ConcurrentBag<InstallationInfo> CompletedInstallations { get; set; }
-
- #region PluginUninstalled Event
- /// <summary>
- /// Occurs when [plugin uninstalled].
- /// </summary>
- public event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled;
-
- /// <summary>
- /// Called when [plugin uninstalled].
- /// </summary>
- /// <param name="plugin">The plugin.</param>
- private void OnPluginUninstalled(IPlugin plugin)
- {
- EventHelper.FireEventIfNotNull(PluginUninstalled, this, new GenericEventArgs<IPlugin> { Argument = plugin }, _logger);
- }
- #endregion
-
- #region PluginUpdated Event
- /// <summary>
- /// Occurs when [plugin updated].
- /// </summary>
- public event EventHandler<GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>>> PluginUpdated;
- /// <summary>
- /// Called when [plugin updated].
- /// </summary>
- /// <param name="plugin">The plugin.</param>
- /// <param name="newVersion">The new version.</param>
- private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion)
- {
- _logger.Info("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification);
-
- EventHelper.FireEventIfNotNull(PluginUpdated, this, new GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> { Argument = new Tuple<IPlugin, PackageVersionInfo>(plugin, newVersion) }, _logger);
-
- _applicationHost.NotifyPendingRestart();
- }
- #endregion
-
- #region PluginInstalled Event
- /// <summary>
- /// Occurs when [plugin updated].
- /// </summary>
- public event EventHandler<GenericEventArgs<PackageVersionInfo>> PluginInstalled;
- /// <summary>
- /// Called when [plugin installed].
- /// </summary>
- /// <param name="package">The package.</param>
- private void OnPluginInstalled(PackageVersionInfo package)
- {
- _logger.Info("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);
-
- EventHelper.FireEventIfNotNull(PluginInstalled, this, new GenericEventArgs<PackageVersionInfo> { Argument = package }, _logger);
-
- _applicationHost.NotifyPendingRestart();
- }
- #endregion
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- private readonly IApplicationPaths _appPaths;
- private readonly IHttpClient _httpClient;
- private readonly IJsonSerializer _jsonSerializer;
- private readonly ISecurityManager _securityManager;
- private readonly IConfigurationManager _config;
- private readonly IFileSystem _fileSystem;
-
- /// <summary>
- /// Gets the application host.
- /// </summary>
- /// <value>The application host.</value>
- private readonly IApplicationHost _applicationHost;
-
- public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem)
- {
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
-
- CurrentInstallations = new List<Tuple<InstallationInfo, CancellationTokenSource>>();
- CompletedInstallations = new ConcurrentBag<InstallationInfo>();
-
- _applicationHost = appHost;
- _appPaths = appPaths;
- _httpClient = httpClient;
- _jsonSerializer = jsonSerializer;
- _securityManager = securityManager;
- _config = config;
- _fileSystem = fileSystem;
- _logger = logger;
- }
-
- private Version GetPackageVersion(PackageVersionInfo version)
- {
- return new Version(ValueOrDefault(version.versionStr, "0.0.0.1"));
- }
-
- private static string ValueOrDefault(string str, string def)
- {
- return string.IsNullOrEmpty(str) ? def : str;
- }
-
- /// <summary>
- /// Gets all available packages.
- /// </summary>
- /// <returns>Task{List{PackageInfo}}.</returns>
- public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
- bool withRegistration = true,
- string packageType = null,
- Version applicationVersion = null)
- {
- var data = new Dictionary<string, string>
- {
- { "key", _securityManager.SupporterKey },
- { "mac", _applicationHost.SystemId },
- { "systemid", _applicationHost.SystemId }
- };
-
- if (withRegistration)
- {
- using (var json = await _httpClient.Post(MbAdmin.HttpsUrl + "service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
-
- return FilterPackages(packages, packageType, applicationVersion);
- }
- }
- else
- {
- var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
-
- return FilterPackages(packages.ToList(), packageType, applicationVersion);
- }
- }
-
- private DateTime _lastPackageUpdateTime;
-
- /// <summary>
- /// Gets all available packages.
- /// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{List{PackageInfo}}.</returns>
- public async Task<IEnumerable<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken)
- {
- _logger.Info("Opening {0}", PackageCachePath);
- try
- {
- using (var stream = _fileSystem.OpenRead(PackageCachePath))
- {
- var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
-
- if (DateTime.UtcNow - _lastPackageUpdateTime > GetCacheLength())
- {
- UpdateCachedPackages(CancellationToken.None, false);
- }
-
- return packages;
- }
- }
- catch (Exception)
- {
-
- }
-
- _lastPackageUpdateTime = DateTime.MinValue;
- await UpdateCachedPackages(cancellationToken, true).ConfigureAwait(false);
- using (var stream = _fileSystem.OpenRead(PackageCachePath))
- {
- return _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
- }
- }
-
- private string PackageCachePath
- {
- get { return Path.Combine(_appPaths.CachePath, "serverpackages.json"); }
- }
-
- private readonly SemaphoreSlim _updateSemaphore = new SemaphoreSlim(1, 1);
- private async Task UpdateCachedPackages(CancellationToken cancellationToken, bool throwErrors)
- {
- await _updateSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- if (DateTime.UtcNow - _lastPackageUpdateTime < GetCacheLength())
- {
- return;
- }
-
- var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
- {
- Url = MbAdmin.HttpUrl + "service/MB3Packages.json",
- CancellationToken = cancellationToken,
- Progress = new Progress<Double>()
-
- }).ConfigureAwait(false);
-
- _fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath));
-
- _fileSystem.CopyFile(tempFile, PackageCachePath, true);
- _lastPackageUpdateTime = DateTime.UtcNow;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error updating package cache", ex);
-
- if (throwErrors)
- {
- throw;
- }
- }
- finally
- {
- _updateSemaphore.Release();
- }
- }
-
- private TimeSpan GetCacheLength()
- {
- switch (_config.CommonConfiguration.SystemUpdateLevel)
- {
- case PackageVersionClass.Beta:
- return TimeSpan.FromMinutes(30);
- case PackageVersionClass.Dev:
- return TimeSpan.FromMinutes(3);
- default:
- return TimeSpan.FromHours(24);
- }
- }
-
- protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages)
- {
- foreach (var package in packages)
- {
- package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
- .OrderByDescending(GetPackageVersion).ToList();
- }
-
- // Remove packages with no versions
- packages = packages.Where(p => p.versions.Any()).ToList();
-
- return packages;
- }
-
- protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages, string packageType, Version applicationVersion)
- {
- foreach (var package in packages)
- {
- package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
- .OrderByDescending(GetPackageVersion).ToList();
- }
-
- if (!string.IsNullOrWhiteSpace(packageType))
- {
- packages = packages.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase)).ToList();
- }
-
- // If an app version was supplied, filter the versions for each package to only include supported versions
- if (applicationVersion != null)
- {
- foreach (var package in packages)
- {
- package.versions = package.versions.Where(v => IsPackageVersionUpToDate(v, applicationVersion)).ToList();
- }
- }
-
- // Remove packages with no versions
- packages = packages.Where(p => p.versions.Any()).ToList();
-
- return packages;
- }
-
- /// <summary>
- /// Determines whether [is package version up to date] [the specified package version info].
- /// </summary>
- /// <param name="packageVersionInfo">The package version info.</param>
- /// <param name="currentServerVersion">The current server version.</param>
- /// <returns><c>true</c> if [is package version up to date] [the specified package version info]; otherwise, <c>false</c>.</returns>
- private bool IsPackageVersionUpToDate(PackageVersionInfo packageVersionInfo, Version currentServerVersion)
- {
- if (string.IsNullOrEmpty(packageVersionInfo.requiredVersionStr))
- {
- return true;
- }
-
- Version requiredVersion;
-
- return Version.TryParse(packageVersionInfo.requiredVersionStr, out requiredVersion) && currentServerVersion >= requiredVersion;
- }
-
- /// <summary>
- /// Gets the package.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="guid">The assembly guid</param>
- /// <param name="classification">The classification.</param>
- /// <param name="version">The version.</param>
- /// <returns>Task{PackageVersionInfo}.</returns>
- public async Task<PackageVersionInfo> GetPackage(string name, string guid, PackageVersionClass classification, Version version)
- {
- var packages = await GetAvailablePackages(CancellationToken.None).ConfigureAwait(false);
-
- var package = packages.FirstOrDefault(p => string.Equals(p.guid, guid ?? "none", StringComparison.OrdinalIgnoreCase))
- ?? packages.FirstOrDefault(p => p.name.Equals(name, StringComparison.OrdinalIgnoreCase));
-
- if (package == null)
- {
- return null;
- }
-
- return package.versions.FirstOrDefault(v => GetPackageVersion(v).Equals(version) && v.classification == classification);
- }
-
- /// <summary>
- /// Gets the latest compatible version.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="guid">The assembly guid if this is a plug-in</param>
- /// <param name="currentServerVersion">The current server version.</param>
- /// <param name="classification">The classification.</param>
- /// <returns>Task{PackageVersionInfo}.</returns>
- public async Task<PackageVersionInfo> GetLatestCompatibleVersion(string name, string guid, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release)
- {
- var packages = await GetAvailablePackages(CancellationToken.None).ConfigureAwait(false);
-
- return GetLatestCompatibleVersion(packages, name, guid, currentServerVersion, classification);
- }
-
- /// <summary>
- /// Gets the latest compatible version.
- /// </summary>
- /// <param name="availablePackages">The available packages.</param>
- /// <param name="name">The name.</param>
- /// <param name="currentServerVersion">The current server version.</param>
- /// <param name="classification">The classification.</param>
- /// <returns>PackageVersionInfo.</returns>
- public PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, string guid, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release)
- {
- var package = availablePackages.FirstOrDefault(p => string.Equals(p.guid, guid ?? "none", StringComparison.OrdinalIgnoreCase))
- ?? availablePackages.FirstOrDefault(p => p.name.Equals(name, StringComparison.OrdinalIgnoreCase));
-
- if (package == null)
- {
- return null;
- }
-
- return package.versions
- .OrderByDescending(GetPackageVersion)
- .FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion));
- }
-
- /// <summary>
- /// Gets the available plugin updates.
- /// </summary>
- /// <param name="applicationVersion">The current server version.</param>
- /// <param name="withAutoUpdateEnabled">if set to <c>true</c> [with auto update enabled].</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
- public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version applicationVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken)
- {
- var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
-
- var plugins = _applicationHost.Plugins.ToList();
-
- if (withAutoUpdateEnabled)
- {
- plugins = plugins
- .Where(p => _config.CommonConfiguration.EnableAutoUpdate)
- .ToList();
- }
-
- // Figure out what needs to be installed
- var packages = plugins.Select(p =>
- {
- var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, _config.CommonConfiguration.SystemUpdateLevel);
-
- return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null;
-
- }).Where(i => i != null).ToList();
-
- return packages
- .Where(p => !string.IsNullOrWhiteSpace(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase)));
- }
-
- /// <summary>
- /// Installs the package.
- /// </summary>
- /// <param name="package">The package.</param>
- /// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
- /// <param name="progress">The progress.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">package</exception>
- public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
- {
- if (package == null)
- {
- throw new ArgumentNullException("package");
- }
-
- if (progress == null)
- {
- throw new ArgumentNullException("progress");
- }
-
- var installationInfo = new InstallationInfo
- {
- Id = Guid.NewGuid().ToString("N"),
- Name = package.name,
- AssemblyGuid = package.guid,
- UpdateClass = package.classification,
- Version = package.versionStr
- };
-
- var innerCancellationTokenSource = new CancellationTokenSource();
-
- var tuple = new Tuple<InstallationInfo, CancellationTokenSource>(installationInfo, innerCancellationTokenSource);
-
- // Add it to the in-progress list
- lock (CurrentInstallations)
- {
- CurrentInstallations.Add(tuple);
- }
-
- var innerProgress = new ActionableProgress<double>();
-
- // Whenever the progress updates, update the outer progress object and InstallationInfo
- innerProgress.RegisterAction(percent =>
- {
- progress.Report(percent);
-
- installationInfo.PercentComplete = percent;
- });
-
- var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;
-
- var installationEventArgs = new InstallationEventArgs
- {
- InstallationInfo = installationInfo,
- PackageVersionInfo = package
- };
-
- EventHelper.FireEventIfNotNull(PackageInstalling, this, installationEventArgs, _logger);
-
- try
- {
- await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false);
-
- lock (CurrentInstallations)
- {
- CurrentInstallations.Remove(tuple);
- }
-
- progress.Report(100);
-
- CompletedInstallations.Add(installationInfo);
-
- EventHelper.FireEventIfNotNull(PackageInstallationCompleted, this, installationEventArgs, _logger);
- }
- catch (OperationCanceledException)
- {
- lock (CurrentInstallations)
- {
- CurrentInstallations.Remove(tuple);
- }
-
- _logger.Info("Package installation cancelled: {0} {1}", package.name, package.versionStr);
-
- EventHelper.FireEventIfNotNull(PackageInstallationCancelled, this, installationEventArgs, _logger);
-
- throw;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Package installation failed", ex);
-
- lock (CurrentInstallations)
- {
- CurrentInstallations.Remove(tuple);
- }
-
- EventHelper.FireEventIfNotNull(PackageInstallationFailed, this, new InstallationFailedEventArgs
- {
- InstallationInfo = installationInfo,
- Exception = ex
-
- }, _logger);
-
- throw;
- }
- finally
- {
- // Dispose the progress object and remove the installation from the in-progress list
- innerProgress.Dispose();
- tuple.Item2.Dispose();
- }
- }
-
- /// <summary>
- /// Installs the package internal.
- /// </summary>
- /// <param name="package">The package.</param>
- /// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
- /// <param name="progress">The progress.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
- {
- // Do the install
- await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);
-
- // Do plugin-specific processing
- if (isPlugin)
- {
- // Set last update time if we were installed before
- var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
- ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase));
-
- if (plugin != null)
- {
- OnPluginUpdated(plugin, package);
- }
- else
- {
- OnPluginInstalled(package);
- }
- }
- }
-
- private async Task PerformPackageInstallation(IProgress<double> progress, PackageVersionInfo package, CancellationToken cancellationToken)
- {
- // Target based on if it is an archive or single assembly
- // zip archives are assumed to contain directory structures relative to our ProgramDataPath
- var extension = Path.GetExtension(package.targetFilename);
- var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase);
- var target = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename);
-
- // Download to temporary file so that, if interrupted, it won't destroy the existing installation
- var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
- {
- Url = package.sourceUrl,
- CancellationToken = cancellationToken,
- Progress = progress
-
- }).ConfigureAwait(false);
-
- cancellationToken.ThrowIfCancellationRequested();
-
- // Validate with a checksum
- var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum);
- if (packageChecksum != Guid.Empty) // support for legacy uploads for now
- {
- using (var crypto = new MD5CryptoServiceProvider())
- using (var stream = new BufferedStream(_fileSystem.OpenRead(tempFile), 100000))
- {
- var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty));
- if (check != packageChecksum)
- {
- throw new ApplicationException(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));
- }
- }
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- // Success - move it to the real target
- try
- {
- _fileSystem.CreateDirectory(Path.GetDirectoryName(target));
- _fileSystem.CopyFile(tempFile, target, true);
- //If it is an archive - write out a version file so we know what it is
- if (isArchive)
- {
- File.WriteAllText(target + ".ver", package.versionStr);
- }
- }
- catch (IOException e)
- {
- _logger.ErrorException("Error attempting to move file from {0} to {1}", e, tempFile, target);
- throw;
- }
-
- try
- {
- _fileSystem.DeleteFile(tempFile);
- }
- catch (IOException e)
- {
- // Don't fail because of this
- _logger.ErrorException("Error deleting temp file {0]", e, tempFile);
- }
- }
-
- /// <summary>
- /// Uninstalls a plugin
- /// </summary>
- /// <param name="plugin">The plugin.</param>
- /// <exception cref="System.ArgumentException"></exception>
- public void UninstallPlugin(IPlugin plugin)
- {
- plugin.OnUninstalling();
-
- // Remove it the quick way for now
- _applicationHost.RemovePlugin(plugin);
-
- _fileSystem.DeleteFile(plugin.AssemblyFilePath);
-
- OnPluginUninstalled(plugin);
-
- _applicationHost.NotifyPendingRestart();
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
- {
- if (dispose)
- {
- lock (CurrentInstallations)
- {
- foreach (var tuple in CurrentInstallations)
- {
- tuple.Item2.Dispose();
- }
-
- CurrentInstallations.Clear();
- }
- }
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
- }
-}