aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Startup.Common
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Startup.Common')
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs43
-rw-r--r--MediaBrowser.Server.Startup.Common/Configuration/ServerConfigurationManager.cs257
-rw-r--r--MediaBrowser.Server.Startup.Common/HttpServerFactory.cs107
-rw-r--r--MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj15
-rw-r--r--MediaBrowser.Server.Startup.Common/ServerApplicationPaths.cs233
-rw-r--r--MediaBrowser.Server.Startup.Common/packages.config1
6 files changed, 647 insertions, 9 deletions
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index e5a17f8fc..b14378eb8 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -50,9 +50,7 @@ using MediaBrowser.Providers.Manager;
using MediaBrowser.Providers.Subtitles;
using MediaBrowser.Server.Implementations;
using MediaBrowser.Server.Implementations.Activity;
-using MediaBrowser.Server.Implementations.Configuration;
using MediaBrowser.Server.Implementations.Devices;
-using MediaBrowser.Server.Implementations.HttpServer;
using MediaBrowser.Server.Implementations.IO;
using MediaBrowser.Server.Implementations.Notifications;
using MediaBrowser.Server.Implementations.Persistence;
@@ -72,6 +70,7 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Emby.Common.Implementations;
@@ -133,8 +132,10 @@ using MediaBrowser.Model.Social;
using MediaBrowser.Model.Text;
using MediaBrowser.Model.Xml;
using MediaBrowser.Server.Implementations.Archiving;
+using MediaBrowser.Server.Startup.Common.Configuration;
using OpenSubtitlesHandler;
using ServiceStack;
+using SocketHttpListener.Primitives;
using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions;
namespace MediaBrowser.Server.Startup.Common
@@ -271,7 +272,7 @@ namespace MediaBrowser.Server.Startup.Common
ILogManager logManager,
StartupOptions options,
IFileSystem fileSystem,
- INativeApp nativeApp,
+ INativeApp nativeApp,
IPowerManagement powerManagement,
string releaseAssetFilename)
: base(applicationPaths, logManager, fileSystem)
@@ -613,7 +614,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
- HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer);
+ HttpServer = HttpServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer, EnvironmentInfo, Certificate);
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
RegisterSingleInstance(HttpServer, false);
progress.Report(10);
@@ -736,6 +737,32 @@ namespace MediaBrowser.Server.Startup.Common
await ((UserManager)UserManager).Initialize().ConfigureAwait(false);
}
+ private ICertificate GetCertificate(string certificateLocation)
+ {
+ if (string.IsNullOrWhiteSpace(certificateLocation))
+ {
+ return null;
+ }
+
+ try
+ {
+ X509Certificate2 localCert = new X509Certificate2(certificateLocation);
+ //localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
+ if (localCert.PrivateKey == null)
+ {
+ //throw new FileNotFoundException("Secure requested, no private key included", certificateLocation);
+ return null;
+ }
+
+ return new Certificate(localCert);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error loading cert from {0}", ex, certificateLocation);
+ return null;
+ }
+ }
+
private IImageProcessor GetImageProcessor()
{
var maxConcurrentImageProcesses = Math.Max(Environment.ProcessorCount, 4);
@@ -969,6 +996,7 @@ namespace MediaBrowser.Server.Startup.Common
}
private string CertificatePath { get; set; }
+ private ICertificate Certificate { get; set; }
private IEnumerable<string> GetUrlPrefixes()
{
@@ -998,10 +1026,11 @@ namespace MediaBrowser.Server.Startup.Common
private void StartServer()
{
CertificatePath = GetCertificatePath(true);
+ Certificate = GetCertificate(CertificatePath);
try
{
- ServerManager.Start(GetUrlPrefixes(), CertificatePath);
+ ServerManager.Start(GetUrlPrefixes());
return;
}
catch (Exception ex)
@@ -1018,7 +1047,7 @@ namespace MediaBrowser.Server.Startup.Common
try
{
- ServerManager.Start(GetUrlPrefixes(), CertificatePath);
+ ServerManager.Start(GetUrlPrefixes());
}
catch (Exception ex)
{
@@ -1298,7 +1327,7 @@ namespace MediaBrowser.Server.Startup.Common
public bool SupportsHttps
{
- get { return !string.IsNullOrWhiteSpace(HttpServer.CertificatePath); }
+ get { return Certificate != null; }
}
public async Task<string> GetLocalApiUrl()
diff --git a/MediaBrowser.Server.Startup.Common/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Startup.Common/Configuration/ServerConfigurationManager.cs
new file mode 100644
index 000000000..756a8d0bf
--- /dev/null
+++ b/MediaBrowser.Server.Startup.Common/Configuration/ServerConfigurationManager.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Emby.Common.Implementations.Configuration;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+
+namespace MediaBrowser.Server.Startup.Common.Configuration
+{
+ /// <summary>
+ /// Class ServerConfigurationManager
+ /// </summary>
+ public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
+ {
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class.
+ /// </summary>
+ /// <param name="applicationPaths">The application paths.</param>
+ /// <param name="logManager">The log manager.</param>
+ /// <param name="xmlSerializer">The XML serializer.</param>
+ /// <param name="fileSystem">The file system.</param>
+ public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
+ : base(applicationPaths, logManager, xmlSerializer, fileSystem)
+ {
+ UpdateMetadataPath();
+ }
+
+ public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
+
+ /// <summary>
+ /// Gets the type of the configuration.
+ /// </summary>
+ /// <value>The type of the configuration.</value>
+ protected override Type ConfigurationType
+ {
+ get { return typeof(ServerConfiguration); }
+ }
+
+ /// <summary>
+ /// Gets the application paths.
+ /// </summary>
+ /// <value>The application paths.</value>
+ public IServerApplicationPaths ApplicationPaths
+ {
+ get { return (IServerApplicationPaths)CommonApplicationPaths; }
+ }
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ /// <value>The configuration.</value>
+ public ServerConfiguration Configuration
+ {
+ get { return (ServerConfiguration)CommonConfiguration; }
+ }
+
+ /// <summary>
+ /// Called when [configuration updated].
+ /// </summary>
+ protected override void OnConfigurationUpdated()
+ {
+ UpdateMetadataPath();
+
+ base.OnConfigurationUpdated();
+ }
+
+ public override void AddParts(IEnumerable<IConfigurationFactory> factories)
+ {
+ base.AddParts(factories);
+
+ UpdateTranscodingTempPath();
+ }
+
+ /// <summary>
+ /// Updates the metadata path.
+ /// </summary>
+ private void UpdateMetadataPath()
+ {
+ string metadataPath;
+
+ if (string.IsNullOrWhiteSpace(Configuration.MetadataPath))
+ {
+ metadataPath = GetInternalMetadataPath();
+ }
+ else
+ {
+ metadataPath = Path.Combine(Configuration.MetadataPath, "metadata");
+ }
+
+ ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath;
+
+ ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath;
+ }
+
+ private string GetInternalMetadataPath()
+ {
+ return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata");
+ }
+
+ /// <summary>
+ /// Updates the transcoding temporary path.
+ /// </summary>
+ private void UpdateTranscodingTempPath()
+ {
+ var encodingConfig = this.GetConfiguration<EncodingOptions>("encoding");
+
+ ((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ?
+ null :
+ Path.Combine(encodingConfig.TranscodingTempPath, "transcoding-temp");
+ }
+
+ protected override void OnNamedConfigurationUpdated(string key, object configuration)
+ {
+ base.OnNamedConfigurationUpdated(key, configuration);
+
+ if (string.Equals(key, "encoding", StringComparison.OrdinalIgnoreCase))
+ {
+ UpdateTranscodingTempPath();
+ }
+ }
+
+ /// <summary>
+ /// Replaces the configuration.
+ /// </summary>
+ /// <param name="newConfiguration">The new configuration.</param>
+ /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
+ public override void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
+ {
+ var newConfig = (ServerConfiguration)newConfiguration;
+
+ ValidatePathSubstitutions(newConfig);
+ ValidateMetadataPath(newConfig);
+ ValidateSslCertificate(newConfig);
+
+ EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
+
+ base.ReplaceConfiguration(newConfiguration);
+ }
+
+
+ /// <summary>
+ /// Validates the SSL certificate.
+ /// </summary>
+ /// <param name="newConfig">The new configuration.</param>
+ /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
+ private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
+ {
+ var serverConfig = (ServerConfiguration)newConfig;
+
+ var newPath = serverConfig.CertificatePath;
+
+ if (!string.IsNullOrWhiteSpace(newPath)
+ && !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath))
+ {
+ // Validate
+ if (!FileSystem.FileExists(newPath))
+ {
+ throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath));
+ }
+ }
+ }
+
+ private void ValidatePathSubstitutions(ServerConfiguration newConfig)
+ {
+ foreach (var map in newConfig.PathSubstitutions)
+ {
+ if (string.IsNullOrWhiteSpace(map.From) || string.IsNullOrWhiteSpace(map.To))
+ {
+ throw new ArgumentException("Invalid path substitution");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Validates the metadata path.
+ /// </summary>
+ /// <param name="newConfig">The new configuration.</param>
+ /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
+ private void ValidateMetadataPath(ServerConfiguration newConfig)
+ {
+ var newPath = newConfig.MetadataPath;
+
+ if (!string.IsNullOrWhiteSpace(newPath)
+ && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath))
+ {
+ // Validate
+ if (!FileSystem.DirectoryExists(newPath))
+ {
+ throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
+ }
+
+ EnsureWriteAccess(newPath);
+ }
+ }
+
+ public void DisableMetadataService(string service)
+ {
+ DisableMetadataService(typeof(Movie), Configuration, service);
+ DisableMetadataService(typeof(Episode), Configuration, service);
+ DisableMetadataService(typeof(Series), Configuration, service);
+ DisableMetadataService(typeof(Season), Configuration, service);
+ DisableMetadataService(typeof(MusicArtist), Configuration, service);
+ DisableMetadataService(typeof(MusicAlbum), Configuration, service);
+ DisableMetadataService(typeof(MusicVideo), Configuration, service);
+ DisableMetadataService(typeof(Video), Configuration, service);
+ }
+
+ private void DisableMetadataService(Type type, ServerConfiguration config, string service)
+ {
+ var options = GetMetadataOptions(type, config);
+
+ if (!options.DisabledMetadataSavers.Contains(service, StringComparer.OrdinalIgnoreCase))
+ {
+ var list = options.DisabledMetadataSavers.ToList();
+
+ list.Add(service);
+
+ options.DisabledMetadataSavers = list.ToArray();
+ }
+ }
+
+ private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config)
+ {
+ var options = config.MetadataOptions
+ .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase));
+
+ if (options == null)
+ {
+ var list = config.MetadataOptions.ToList();
+
+ options = new MetadataOptions
+ {
+ ItemType = type.Name
+ };
+
+ list.Add(options);
+
+ config.MetadataOptions = list.ToArray();
+ }
+
+ return options;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Startup.Common/HttpServerFactory.cs b/MediaBrowser.Server.Startup.Common/HttpServerFactory.cs
new file mode 100644
index 000000000..c0c376996
--- /dev/null
+++ b/MediaBrowser.Server.Startup.Common/HttpServerFactory.cs
@@ -0,0 +1,107 @@
+using System;
+using System.IO;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
+using Emby.Common.Implementations.Net;
+using Emby.Server.Implementations.HttpServer;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.System;
+using MediaBrowser.Model.Text;
+using ServiceStack.Text.Jsv;
+using SocketHttpListener.Primitives;
+
+namespace MediaBrowser.Server.Startup.Common
+{
+ /// <summary>
+ /// Class ServerFactory
+ /// </summary>
+ public static class HttpServerFactory
+ {
+ /// <summary>
+ /// Creates the server.
+ /// </summary>
+ /// <returns>IHttpServer.</returns>
+ public static IHttpServer CreateServer(IServerApplicationHost applicationHost,
+ ILogManager logManager,
+ IServerConfigurationManager config,
+ INetworkManager networkmanager,
+ IMemoryStreamFactory streamProvider,
+ string serverName,
+ string defaultRedirectpath,
+ ITextEncoding textEncoding,
+ ISocketFactory socketFactory,
+ ICryptoProvider cryptoProvider,
+ IJsonSerializer json,
+ IXmlSerializer xml,
+ IEnvironmentInfo environment,
+ ICertificate certificate)
+ {
+ var logger = logManager.GetLogger("HttpServer");
+
+ return new HttpListenerHost(applicationHost,
+ logger,
+ config,
+ serverName,
+ defaultRedirectpath,
+ networkmanager,
+ streamProvider,
+ textEncoding,
+ socketFactory,
+ cryptoProvider,
+ json,
+ xml,
+ environment,
+ certificate,
+ new StreamFactory(),
+ GetParseFn);
+ }
+
+ private static Func<string, object> GetParseFn(Type propertyType)
+ {
+ return s => JsvReader.GetParseFn(propertyType)(s);
+ }
+ }
+
+ public class StreamFactory : IStreamFactory
+ {
+ public Stream CreateNetworkStream(ISocket socket, bool ownsSocket)
+ {
+ var netSocket = (NetSocket)socket;
+
+ return new NetworkStream(netSocket.Socket, ownsSocket);
+ }
+
+ public Task AuthenticateSslStreamAsServer(Stream stream, ICertificate certificate)
+ {
+ var sslStream = (SslStream)stream;
+ var cert = (Certificate)certificate;
+
+ return sslStream.AuthenticateAsServerAsync(cert.X509Certificate);
+ }
+
+ public Stream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen)
+ {
+ return new SslStream(innerStream, leaveInnerStreamOpen);
+ }
+ }
+
+ public class Certificate : ICertificate
+ {
+ public Certificate(X509Certificate x509Certificate)
+ {
+ X509Certificate = x509Certificate;
+ }
+
+ public X509Certificate X509Certificate { get; private set; }
+ }
+}
diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index 7e01fd36d..7ac020cc4 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -49,14 +49,22 @@
<HintPath>..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll</HintPath>
<Private>True</Private>
</Reference>
- <Reference Include="ServiceStack.Text, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <Reference Include="ServiceStack, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
+ <HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
+ </Reference>
+ <Reference Include="ServiceStack.Text, Version=4.5.4.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\ServiceStack.Text.4.5.4\lib\net45\ServiceStack.Text.dll</HintPath>
+ <Private>True</Private>
</Reference>
<Reference Include="SimpleInjector, Version=3.2.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<HintPath>..\packages\SimpleInjector.3.2.4\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private>
</Reference>
+ <Reference Include="SocketHttpListener.Portable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\ThirdParty\emby\SocketHttpListener.Portable.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
@@ -73,10 +81,12 @@
<Compile Include="ApplicationHost.cs" />
<Compile Include="ApplicationPathHelper.cs" />
<Compile Include="Browser\BrowserLauncher.cs" />
+ <Compile Include="Configuration\ServerConfigurationManager.cs" />
<Compile Include="EntryPoints\StartupWizard.cs" />
<Compile Include="FFMpeg\FFMpegLoader.cs" />
<Compile Include="FFMpeg\FFMpegInstallInfo.cs" />
<Compile Include="FFMpeg\FFMpegInfo.cs" />
+ <Compile Include="HttpServerFactory.cs" />
<Compile Include="INativeApp.cs" />
<Compile Include="MbLinkShortcutHandler.cs" />
<Compile Include="Migrations\IVersionMigration.cs" />
@@ -103,6 +113,7 @@
<Compile Include="Security\X509Extension.cs" />
<Compile Include="Security\X509Extensions.cs" />
<Compile Include="Security\X520Attributes.cs" />
+ <Compile Include="ServerApplicationPaths.cs" />
<Compile Include="StartupOptions.cs" />
<Compile Include="SystemEvents.cs" />
<Compile Include="TextLocalizer.cs" />
diff --git a/MediaBrowser.Server.Startup.Common/ServerApplicationPaths.cs b/MediaBrowser.Server.Startup.Common/ServerApplicationPaths.cs
new file mode 100644
index 000000000..11de1c4ab
--- /dev/null
+++ b/MediaBrowser.Server.Startup.Common/ServerApplicationPaths.cs
@@ -0,0 +1,233 @@
+using System.IO;
+using Emby.Common.Implementations;
+using MediaBrowser.Controller;
+
+namespace MediaBrowser.Server.Startup.Common
+{
+ /// <summary>
+ /// Extends BaseApplicationPaths to add paths that are only applicable on the server
+ /// </summary>
+ public class ServerApplicationPaths : BaseApplicationPaths, IServerApplicationPaths
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseApplicationPaths" /> class.
+ /// </summary>
+ public ServerApplicationPaths(string programDataPath, string applicationPath, string applicationResourcesPath)
+ : base(programDataPath, applicationPath)
+ {
+ ApplicationResourcesPath = applicationResourcesPath;
+ }
+
+ public string ApplicationResourcesPath { get; private set; }
+
+ /// <summary>
+ /// Gets the path to the base root media directory
+ /// </summary>
+ /// <value>The root folder path.</value>
+ public string RootFolderPath
+ {
+ get
+ {
+ return Path.Combine(ProgramDataPath, "root");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the default user view directory. Used if no specific user view is defined.
+ /// </summary>
+ /// <value>The default user views path.</value>
+ public string DefaultUserViewsPath
+ {
+ get
+ {
+ return Path.Combine(RootFolderPath, "default");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to localization data.
+ /// </summary>
+ /// <value>The localization path.</value>
+ public string LocalizationPath
+ {
+ get
+ {
+ return Path.Combine(ProgramDataPath, "localization");
+ }
+ }
+
+ /// <summary>
+ /// The _ibn path
+ /// </summary>
+ private string _ibnPath;
+ /// <summary>
+ /// Gets the path to the Images By Name directory
+ /// </summary>
+ /// <value>The images by name path.</value>
+ public string ItemsByNamePath
+ {
+ get
+ {
+ return _ibnPath ?? (_ibnPath = Path.Combine(ProgramDataPath, "ImagesByName"));
+ }
+ set
+ {
+ _ibnPath = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the People directory
+ /// </summary>
+ /// <value>The people path.</value>
+ public string PeoplePath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "People");
+ }
+ }
+
+ public string ArtistsPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "artists");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the Genre directory
+ /// </summary>
+ /// <value>The genre path.</value>
+ public string GenrePath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "Genre");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the Genre directory
+ /// </summary>
+ /// <value>The genre path.</value>
+ public string MusicGenrePath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "MusicGenre");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the Studio directory
+ /// </summary>
+ /// <value>The studio path.</value>
+ public string StudioPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "Studio");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the Year directory
+ /// </summary>
+ /// <value>The year path.</value>
+ public string YearPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "Year");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the General IBN directory
+ /// </summary>
+ /// <value>The general path.</value>
+ public string GeneralPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "general");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the Ratings IBN directory
+ /// </summary>
+ /// <value>The ratings path.</value>
+ public string RatingsPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "ratings");
+ }
+ }
+
+ /// <summary>
+ /// Gets the media info images path.
+ /// </summary>
+ /// <value>The media info images path.</value>
+ public string MediaInfoImagesPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "mediainfo");
+ }
+ }
+
+ /// <summary>
+ /// Gets the path to the user configuration directory
+ /// </summary>
+ /// <value>The user configuration directory path.</value>
+ public string UserConfigurationDirectoryPath
+ {
+ get
+ {
+ return Path.Combine(ConfigurationDirectoryPath, "users");
+ }
+ }
+
+ private string _transcodingTempPath;
+ public string TranscodingTempPath
+ {
+ get
+ {
+ return _transcodingTempPath ?? (_transcodingTempPath = Path.Combine(ProgramDataPath, "transcoding-temp"));
+ }
+ set
+ {
+ _transcodingTempPath = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the game genre path.
+ /// </summary>
+ /// <value>The game genre path.</value>
+ public string GameGenrePath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "GameGenre");
+ }
+ }
+
+ private string _internalMetadataPath;
+ public string InternalMetadataPath
+ {
+ get
+ {
+ return _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata"));
+ }
+ set
+ {
+ _internalMetadataPath = value;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Startup.Common/packages.config b/MediaBrowser.Server.Startup.Common/packages.config
index ea3d0e7f8..fa1cc928c 100644
--- a/MediaBrowser.Server.Startup.Common/packages.config
+++ b/MediaBrowser.Server.Startup.Common/packages.config
@@ -3,5 +3,6 @@
<package id="MediaBrowser.Naming" version="1.0.0.59" targetFramework="net46" />
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.6" targetFramework="net46" />
+ <package id="ServiceStack.Text" version="4.5.4" targetFramework="net46" />
<package id="SimpleInjector" version="3.2.4" targetFramework="net46" />
</packages> \ No newline at end of file