diff --git a/.dockerignore b/.dockerignore
index fc4d8ed26d..54b0aa3a7e 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -3,3 +3,6 @@
Dockerfile
CONTRIBUTORS.md
README.md
+deployment/*/dist
+deployment/*/pkg-dist
+deployment/collect-dist/
diff --git a/.gitignore b/.gitignore
index 880e63a7f9..ec683f38f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-!*
-
.directory
#################
@@ -49,6 +47,8 @@ ProgramData-UI*/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+.vs/
+
# User-specific files
*.suo
*.user
@@ -204,7 +204,6 @@ $RECYCLE.BIN/
# Mac crap
.DS_Store
-
#############
## Python
#############
@@ -234,23 +233,33 @@ pip-log.txt
#Mr Developer
.mr.developer.cfg
-/.vs
##########
# Rider
##########
.idea/
+##########
+# Visual Studio Code
+##########
+.vscode/
+
#########################
-# Debian build artifacts
+# Build artifacts
#########################
-debian/.debhelper/
-debian/*.debhelper
-debian/debhelper-build-stamp
-debian/files
-debian/jellyfin.substvars
-debian/jellyfin/
-
+# Artifacts for debian-x64
+deployment/debian-package-x64/pkg-src/.debhelper/
+deployment/debian-package-x64/pkg-src/*.debhelper
+deployment/debian-package-x64/pkg-src/debhelper-build-stamp
+deployment/debian-package-x64/pkg-src/files
+deployment/debian-package-x64/pkg-src/jellyfin.substvars
+deployment/debian-package-x64/pkg-src/jellyfin/
# Don't ignore the debian/bin folder
-!debian/bin/
+!deployment/debian-package-x64/pkg-src/bin/
+
+deployment/**/dist/
+deployment/**/pkg-dist/
+deployment/**/pkg-dist-tmp/
+deployment/collect-dist/
+
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index c88f4cbcd4..f33f48fb33 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -12,6 +12,7 @@
- [sparky8251](https://github.com/sparky8251)
- [LeoVerto](https://github.com/LeoVerto)
- [grafixeyehero](https://github.com/grafixeyehero)
+ - [cvium](https://github.com/cvium)
# Emby Contributors
diff --git a/Dockerfile b/Dockerfile
index e4cbede80c..02332d40b4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,6 +26,6 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=ffmpeg /ffmpeg-bin/* /usr/bin/
EXPOSE 8096
VOLUME /config /media
-RUN apt update \
- && apt install -y libfontconfig1 # needed for Skia
+RUN apt-get update \
+ && apt-get install -y libfontconfig1 --no-install-recommends # needed for Skia
ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config
diff --git a/Dockerfile.aarch64 b/Dockerfile.arm
similarity index 81%
rename from Dockerfile.aarch64
rename to Dockerfile.arm
index cc70ef32f2..a0b3d0e1da 100644
--- a/Dockerfile.aarch64
+++ b/Dockerfile.arm
@@ -3,6 +3,7 @@ ARG DOTNET_VERSION=3.0
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder
WORKDIR /repo
COPY . .
+#TODO Remove or update the sed line when we update dotnet version.
RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \
&& find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \
&& dotnet clean \
@@ -14,7 +15,7 @@ RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime
COPY --from=builder /jellyfin /jellyfin
EXPOSE 8096
-RUN apt update \
- && apt install -y ffmpeg
+RUN apt-get update \
+ && apt-get install -y ffmpeg
VOLUME /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 5c410fe250..d5c206842f 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -54,7 +54,11 @@ using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
+<<<<<<< HEAD
using MediaBrowser.Common.Security;
+=======
+using MediaBrowser.Model.Extensions;
+>>>>>>> dev
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Authentication;
@@ -340,11 +344,6 @@ namespace Emby.Server.Implementations
///
/// The installation manager.
protected IInstallationManager InstallationManager { get; private set; }
- ///
- /// Gets the security manager.
- ///
- /// The security manager.
- protected ISecurityManager SecurityManager { get; private set; }
///
/// Gets or sets the zip client.
@@ -804,10 +803,7 @@ namespace Emby.Server.Implementations
SocketFactory = new SocketFactory(LoggerFactory.CreateLogger("SocketFactory"));
RegisterSingleInstance(SocketFactory);
- SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LoggerFactory, FileSystemManager, CryptographyProvider);
- RegisterSingleInstance(SecurityManager);
-
- InstallationManager = new InstallationManager(LoggerFactory.CreateLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime);
+ InstallationManager = new InstallationManager(LoggerFactory.CreateLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime);
RegisterSingleInstance(InstallationManager);
ZipClient = new ZipClient(FileSystemManager);
@@ -922,7 +918,7 @@ namespace Emby.Server.Implementations
PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LoggerFactory.CreateLogger("PlaylistManager"), UserManager, ProviderManager);
RegisterSingleInstance(PlaylistManager);
- LiveTvManager = new LiveTvManager(this, HttpClient, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager, SecurityManager, () => ChannelManager);
+ LiveTvManager = new LiveTvManager(this, HttpClient, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager, () => ChannelManager);
RegisterSingleInstance(LiveTvManager);
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager);
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index 6ae56c2add..8ae66843c4 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -12,7 +12,6 @@ using Emby.Server.Implementations.Net;
using Emby.Server.Implementations.Services;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Security;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
@@ -85,7 +84,6 @@ namespace Emby.Server.Implementations.HttpServer
{typeof (FileNotFoundException), 404},
//{typeof (DirectoryNotFoundException), 404},
{typeof (SecurityException), 401},
- {typeof (PaymentRequiredException), 402},
{typeof (ArgumentException), 400}
};
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index f48d59040e..4ec57096f0 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -451,18 +451,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public ChannelInfo GetChannelByNumber(string number)
{
- ChannelInfo result = null;
-
- ChannelsByNumber.TryGetValue(number, out result);
+ ChannelsByNumber.TryGetValue(number, out var result);
return result;
}
public ChannelInfo GetChannelByName(string name)
{
- ChannelInfo result = null;
-
- ChannelsByName.TryGetValue(name, out result);
+ ChannelsByName.TryGetValue(name, out var result);
return result;
}
@@ -1178,14 +1174,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- var registration = await _liveTvManager.GetRegistrationInfo("dvr").ConfigureAwait(false);
- if (!registration.IsValid)
- {
- _logger.LogWarning("Emby Premiere required to use Emby DVR.");
- OnTimerOutOfDate(timer);
- return;
- }
-
var activeRecordingInfo = new ActiveRecordingInfo
{
CancellationTokenSource = new CancellationTokenSource(),
@@ -2372,41 +2360,57 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var allTimers = GetTimersForSeries(seriesTimer)
.ToList();
- var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false);
var enabledTimersForSeries = new List();
-
- if (registration.IsValid)
+ foreach (var timer in allTimers)
{
- foreach (var timer in allTimers)
+ var existingTimer = _timerProvider.GetTimer(timer.Id);
+
+ if (existingTimer == null)
{
- var existingTimer = _timerProvider.GetTimer(timer.Id);
+ existingTimer = string.IsNullOrWhiteSpace(timer.ProgramId)
+ ? null
+ : _timerProvider.GetTimerByProgramId(timer.ProgramId);
+ }
- if (existingTimer == null)
+ if (existingTimer == null)
+ {
+ if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer))
{
- existingTimer = string.IsNullOrWhiteSpace(timer.ProgramId)
- ? null
- : _timerProvider.GetTimerByProgramId(timer.ProgramId);
+ timer.Status = RecordingStatus.Cancelled;
}
+ else
+ {
+ enabledTimersForSeries.Add(timer);
+ }
+ _timerProvider.Add(timer);
+
+ TimerCreated?.Invoke(this, new GenericEventArgs(timer));
+ }
+ // Only update if not currently active - test both new timer and existing in case Id's are different
+ // Id's could be different if the timer was created manually prior to series timer creation
+ else if (!_activeRecordings.TryGetValue(timer.Id, out _) && !_activeRecordings.TryGetValue(existingTimer.Id, out _))
+ {
+ UpdateExistingTimerWithNewMetadata(existingTimer, timer);
+
+ // Needed by ShouldCancelTimerForSeriesTimer
+ timer.IsManual = existingTimer.IsManual;
- if (existingTimer == null)
+ if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer))
{
- if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer))
- {
- timer.Status = RecordingStatus.Cancelled;
- }
- else
- {
- enabledTimersForSeries.Add(timer);
- }
- _timerProvider.Add(timer);
+ existingTimer.Status = RecordingStatus.Cancelled;
+ }
+ else if (!existingTimer.IsManual)
+ {
+ existingTimer.Status = RecordingStatus.New;
+ }
- if (TimerCreated != null)
- {
- TimerCreated(this, new GenericEventArgs(timer));
- }
+ if (existingTimer.Status != RecordingStatus.Cancelled)
+ {
+ enabledTimersForSeries.Add(existingTimer);
}
- else
+
+ if (updateTimerSettings)
{
// Only update if not currently active - test both new timer and existing in case Id's are different
// Id's could be different if the timer was created manually prior to series timer creation
@@ -2445,6 +2449,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.Update(existingTimer);
}
}
+
+ existingTimer.SeriesTimerId = seriesTimer.Id;
+ _timerProvider.Update(existingTimer);
}
}
@@ -2770,15 +2777,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var configuredDevice = configuredDevices.FirstOrDefault(i => string.Equals(i.DeviceId, device.DeviceId, StringComparison.OrdinalIgnoreCase));
- if (configuredDevice != null)
+ if (configuredDevice != null && !string.Equals(device.Url, configuredDevice.Url, StringComparison.OrdinalIgnoreCase))
{
- if (!string.Equals(device.Url, configuredDevice.Url, StringComparison.OrdinalIgnoreCase))
- {
- _logger.LogInformation("Tuner url has changed from {0} to {1}", configuredDevice.Url, device.Url);
+ _logger.LogInformation("Tuner url has changed from {PreviousUrl} to {NewUrl}", configuredDevice.Url, device.Url);
- configuredDevice.Url = device.Url;
- await _liveTvManager.SaveTunerHost(configuredDevice).ConfigureAwait(false);
- }
+ configuredDevice.Url = device.Url;
+ await _liveTvManager.SaveTunerHost(configuredDevice).ConfigureAwait(false);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 6efbefd5d6..4b2d160661 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -51,7 +51,6 @@ namespace Emby.Server.Implementations.LiveTv
private readonly ITaskManager _taskManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly IProviderManager _providerManager;
- private readonly ISecurityManager _security;
private readonly Func _channelManager;
private readonly IDtoService _dtoService;
@@ -78,7 +77,23 @@ namespace Emby.Server.Implementations.LiveTv
private IServerApplicationHost _appHost;
private IHttpClient _httpClient;
- public LiveTvManager(IServerApplicationHost appHost, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem, ISecurityManager security, Func channelManager)
+ public LiveTvManager(
+ IServerApplicationHost appHost,
+ IHttpClient httpClient,
+ IServerConfigurationManager config,
+ ILogger logger,
+ IItemRepository itemRepo,
+ IImageProcessor imageProcessor,
+ IUserDataManager userDataManager,
+ IDtoService dtoService,
+ IUserManager userManager,
+ ILibraryManager libraryManager,
+ ITaskManager taskManager,
+ ILocalizationManager localization,
+ IJsonSerializer jsonSerializer,
+ IProviderManager providerManager,
+ IFileSystem fileSystem,
+ Func channelManager)
{
_appHost = appHost;
_config = config;
@@ -91,7 +106,6 @@ namespace Emby.Server.Implementations.LiveTv
_jsonSerializer = jsonSerializer;
_providerManager = providerManager;
_fileSystem = fileSystem;
- _security = security;
_dtoService = dtoService;
_userDataManager = userDataManager;
_channelManager = channelManager;
@@ -2085,14 +2099,6 @@ namespace Emby.Server.Implementations.LiveTv
public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
{
- var registration = await GetRegistrationInfo("seriesrecordings").ConfigureAwait(false);
-
- if (!registration.IsValid)
- {
- _logger.LogInformation("Creating series recordings requires an active Emby Premiere subscription.");
- return;
- }
-
var service = GetService(timer.ServiceName);
var info = await _tvDtoService.GetSeriesTimerInfo(timer, true, this, cancellationToken).ConfigureAwait(false);
@@ -2434,30 +2440,6 @@ namespace Emby.Server.Implementations.LiveTv
}
}
- public Task GetRegistrationInfo(string feature)
- {
- if (string.Equals(feature, "seriesrecordings", StringComparison.OrdinalIgnoreCase))
- {
- feature = "embytvseriesrecordings";
- }
-
- if (string.Equals(feature, "dvr-l", StringComparison.OrdinalIgnoreCase))
- {
- var config = GetConfiguration();
- if (config.TunerHosts.Length > 0 &&
- config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0)
- {
- return Task.FromResult(new MBRegistrationRecord
- {
- IsRegistered = true,
- IsValid = true
- });
- }
- }
-
- return _security.GetRegistrationStatus(feature);
- }
-
public Task> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken)
{
var info = GetConfiguration().ListingProviders.First(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
diff --git a/Emby.Server.Implementations/Security/MBLicenseFile.cs b/Emby.Server.Implementations/Security/MBLicenseFile.cs
deleted file mode 100644
index 91fbb4a2c8..0000000000
--- a/Emby.Server.Implementations/Security/MBLicenseFile.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-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 _updateRecords = new ConcurrentDictionary();
- 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);
-
- _updateRecords.TryRemove(key, out var 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());
- }
- }
- catch (IOException)
- {
- lock (_fileLock)
- {
- _fileSystem.WriteAllBytes(licenseFile, Array.Empty());
- }
- }
- }
- 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;
- }
-
- if (Guid.TryParse(line, out var feat))
- {
- var lineParts = contents[i + 1].Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (long.TryParse(lineParts[0], out var 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
- {
- 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;
- }
- }
-}
diff --git a/Emby.Server.Implementations/Security/PluginSecurityManager.cs b/Emby.Server.Implementations/Security/PluginSecurityManager.cs
deleted file mode 100644
index cb224627c6..0000000000
--- a/Emby.Server.Implementations/Security/PluginSecurityManager.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Controller;
-using MediaBrowser.Model.Cryptography;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.Serialization;
-using Microsoft.Extensions.Logging;
-
-namespace Emby.Server.Implementations.Security
-{
- ///
- /// Class PluginSecurityManager
- ///
- public class PluginSecurityManager : ISecurityManager
- {
- private const string MBValidateUrl = "https://mb3admin.local/admin/service/registration/validate";
- private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "https://mb3admin.local/admin/service/appstore/register";
-
- public async Task IsSupporter()
- {
- var result = await GetRegistrationStatusInternal("MBSupporter", false, _appHost.ApplicationVersion.ToString(), CancellationToken.None).ConfigureAwait(false);
-
- return result.IsRegistered;
- }
-
- private MBLicenseFile _licenseFile;
- private MBLicenseFile LicenseFile => _licenseFile ?? (_licenseFile = new MBLicenseFile(_appPaths, _fileSystem, _cryptographyProvider));
-
- private readonly IHttpClient _httpClient;
- private readonly IJsonSerializer _jsonSerializer;
- private readonly IServerApplicationHost _appHost;
- private readonly ILogger _logger;
- private readonly IApplicationPaths _appPaths;
- private readonly IFileSystem _fileSystem;
- private readonly ICryptoProvider _cryptographyProvider;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public PluginSecurityManager(IServerApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer,
- IApplicationPaths appPaths, ILoggerFactory loggerFactory, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
- {
- if (httpClient == null)
- {
- throw new ArgumentNullException(nameof(httpClient));
- }
-
- _appHost = appHost;
- _httpClient = httpClient;
- _jsonSerializer = jsonSerializer;
- _appPaths = appPaths;
- _fileSystem = fileSystem;
- _cryptographyProvider = cryptographyProvider;
- _logger = loggerFactory.CreateLogger("SecurityManager");
- }
-
- ///
- /// Gets the registration status.
- /// This overload supports existing plug-ins.
- ///
- public Task GetRegistrationStatus(string feature)
- {
- return GetRegistrationStatusInternal(feature, false, null, CancellationToken.None);
- }
-
- ///
- /// Gets or sets the supporter key.
- ///
- /// The supporter key.
- public string SupporterKey
- {
- get => LicenseFile.RegKey;
- set => throw new Exception("Please call UpdateSupporterKey");
- }
-
- public async Task UpdateSupporterKey(string newValue)
- {
- if (newValue != null)
- {
- newValue = newValue.Trim();
- }
-
- if (!string.Equals(newValue, LicenseFile.RegKey, StringComparison.Ordinal))
- {
- LicenseFile.RegKey = newValue;
- LicenseFile.Save();
-
- // Reset this
- await GetRegistrationStatusInternal("MBSupporter", true, _appHost.ApplicationVersion.ToString(), CancellationToken.None).ConfigureAwait(false);
- }
- }
-
- ///
- /// 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.
- ///
- /// Json parameters to send to admin server
- 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 = await _jsonSerializer.DeserializeFromStreamAsync(response.Content).ConfigureAwait(false);
-
- if (reg == null)
- {
- var msg = "Result from appstore registration was null.";
- _logger.LogError(msg);
- throw new ArgumentException(msg);
- }
- if (!string.IsNullOrEmpty(reg.key))
- {
- await UpdateSupporterKey(reg.key).ConfigureAwait(false);
- }
- }
-
- }
- catch (ArgumentException)
- {
- SaveAppStoreInfo(parameters);
- throw;
- }
- catch (HttpException ex)
- {
- _logger.LogError(ex, "Error registering appstore purchase {parameters}", parameters ?? "NO PARMS SENT");
-
- throw new Exception("Error registering store sale");
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error registering appstore purchase {parameters}", 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 Exception("Error registering store sale");
- }
-
- }
-
- private void SaveAppStoreInfo(string info)
- {
- // Save all transaction information to a file
-
- try
- {
- _fileSystem.WriteAllText(Path.Combine(_appPaths.ProgramDataPath, "apptrans-error.txt"), info);
- }
- catch (IOException)
- {
-
- }
- }
-
- private SemaphoreSlim _regCheckLock = new SemaphoreSlim(1, 1);
-
- private async Task GetRegistrationStatusInternal(string feature, bool forceCallToServer, string version, CancellationToken cancellationToken)
- {
- await _regCheckLock.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- var record = new MBRegistrationRecord
- {
- IsRegistered = true,
- RegChecked = true,
- TrialVersion = false,
- IsValid = true,
- RegError = false
- };
-
- return record;
- }
- finally
- {
- _regCheckLock.Release();
- }
- }
-
- 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;
- }
- }
-}
diff --git a/Emby.Server.Implementations/Security/RegRecord.cs b/Emby.Server.Implementations/Security/RegRecord.cs
deleted file mode 100644
index 11a02e0e76..0000000000
--- a/Emby.Server.Implementations/Security/RegRecord.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-
-namespace Emby.Server.Implementations.Security
-{
- class RegRecord
- {
- public string featId { get; set; }
- public bool registered { get; set; }
- public DateTime expDate { get; set; }
- public string key { get; set; }
- }
-}
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 6ed6f127b5..6e69ecb56c 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -10,7 +10,6 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Progress;
-using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Cryptography;
@@ -107,7 +106,6 @@ namespace Emby.Server.Implementations.Updates
private readonly IApplicationPaths _appPaths;
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _jsonSerializer;
- private readonly ISecurityManager _securityManager;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
@@ -122,7 +120,16 @@ namespace Emby.Server.Implementations.Updates
// netframework or netcore
private readonly string _packageRuntime;
- public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IServerConfigurationManager config, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, string packageRuntime)
+ public InstallationManager(
+ ILogger logger,
+ IApplicationHost appHost,
+ IApplicationPaths appPaths,
+ IHttpClient httpClient,
+ IJsonSerializer jsonSerializer,
+ IServerConfigurationManager config,
+ IFileSystem fileSystem,
+ ICryptoProvider cryptographyProvider,
+ string packageRuntime)
{
if (logger == null)
{
@@ -136,7 +143,6 @@ namespace Emby.Server.Implementations.Updates
_appPaths = appPaths;
_httpClient = httpClient;
_jsonSerializer = jsonSerializer;
- _securityManager = securityManager;
_config = config;
_fileSystem = fileSystem;
_cryptographyProvider = cryptographyProvider;
@@ -163,41 +169,10 @@ namespace Emby.Server.Implementations.Updates
string packageType = null,
Version applicationVersion = null)
{
- if (withRegistration)
- {
- var data = new Dictionary
- {
- { "key", _securityManager.SupporterKey },
- { "mac", _applicationHost.SystemId },
- { "systemid", _applicationHost.SystemId }
- };
-
- var options = new HttpRequestOptions
- {
- Url = "https://www.mb3admin.local/admin/service/package/retrieveall?includeAllRuntimes=true",
- CancellationToken = cancellationToken
- };
-
- options.SetPostData(data);
-
- using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false))
- {
- using (var json = response.Content)
- {
- cancellationToken.ThrowIfCancellationRequested();
+ // TODO cvium: when plugins get back this would need to be fixed
+ // var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
- var packages = await _jsonSerializer.DeserializeFromStreamAsync(json).ConfigureAwait(false);
-
- return FilterPackages(packages, packageType, applicationVersion);
- }
- }
- }
- else
- {
- var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
-
- return FilterPackages(packages, packageType, applicationVersion);
- }
+ return new List(); //FilterPackages(packages, packageType, applicationVersion);
}
///
diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs
index 02827f554f..6abfb024aa 100644
--- a/MediaBrowser.Api/PluginService.cs
+++ b/MediaBrowser.Api/PluginService.cs
@@ -10,7 +10,6 @@ using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
@@ -79,6 +78,16 @@ namespace MediaBrowser.Api
public Stream RequestStream { get; set; }
}
+ //TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins,
+ // delete all these registration endpoints. They are only kept for compatibility.
+ [Route("/Registrations/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)]
+ [Authenticated]
+ public class GetRegistration : IReturn
+ {
+ [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Name { get; set; }
+ }
+
///
/// Class GetPluginSecurityInfo
///
@@ -105,14 +114,7 @@ namespace MediaBrowser.Api
public string Name { get; set; }
}
- [Route("/Registrations/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)]
- [Authenticated]
- public class GetRegistration : IReturn
- {
- [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
- }
-
+ // TODO these two classes are only kept for compability with paid plugins and should be removed
public class RegistrationInfo
{
public string Name { get; set; }
@@ -121,14 +123,21 @@ namespace MediaBrowser.Api
public bool IsRegistered { get; set; }
}
- [Route("/Appstore/Register", "POST", Summary = "Registers an appstore sale", IsHidden = true)]
- [Authenticated]
- public class RegisterAppstoreSale
+ public class MBRegistrationRecord
{
- [ApiMember(Name = "Parameters", Description = "Java representation of parameters to pass through to admin server", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Parameters { get; set; }
+ public DateTime ExpirationDate { get; set; }
+ public bool IsRegistered { get; set; }
+ public bool RegChecked { get; set; }
+ public bool RegError { get; set; }
+ public bool TrialVersion { get; set; }
+ public bool IsValid { get; set; }
}
+ public class PluginSecurityInfo
+ {
+ public string SupporterKey { get; set; }
+ public bool IsMBSupporter { get; set; }
+ }
///
/// Class PluginsService
///
@@ -143,14 +152,11 @@ namespace MediaBrowser.Api
/// The _app host
///
private readonly IApplicationHost _appHost;
-
- private readonly ISecurityManager _securityManager;
-
private readonly IInstallationManager _installationManager;
private readonly INetworkManager _network;
private readonly IDeviceManager _deviceManager;
- public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost, ISecurityManager securityManager, IInstallationManager installationManager, INetworkManager network, IDeviceManager deviceManager)
+ public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost, IInstallationManager installationManager, INetworkManager network, IDeviceManager deviceManager)
: base()
{
if (jsonSerializer == null)
@@ -159,7 +165,6 @@ namespace MediaBrowser.Api
}
_appHost = appHost;
- _securityManager = securityManager;
_installationManager = installationManager;
_network = network;
_deviceManager = deviceManager;
@@ -173,20 +178,26 @@ namespace MediaBrowser.Api
/// System.Object.
public async Task