mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-10 00:02:56 +01:00
Merge remote-tracking branch 'upstream/master' into support-running-without-web-content
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
@@ -6,29 +8,6 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
{
|
||||
public class ConfigurationPageInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name { get; set; }
|
||||
public bool EnableInMainMenu { get; set; }
|
||||
public string MenuSection { get; set; }
|
||||
public string MenuIcon { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the configuration page.
|
||||
/// </summary>
|
||||
/// <value>The type of the configuration page.</value>
|
||||
public ConfigurationPageType ConfigurationPageType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the plugin id.
|
||||
/// </summary>
|
||||
/// <value>The plugin id.</value>
|
||||
public string PluginId { get; set; }
|
||||
|
||||
public ConfigurationPageInfo(IPluginConfigurationPage page)
|
||||
{
|
||||
Name = page.Name;
|
||||
@@ -54,5 +33,31 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
// Don't use "N" because it needs to match Plugin.Id
|
||||
PluginId = plugin.Id.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool EnableInMainMenu { get; set; }
|
||||
|
||||
public string MenuSection { get; set; }
|
||||
|
||||
public string MenuIcon { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the configuration page.
|
||||
/// </summary>
|
||||
/// <value>The type of the configuration page.</value>
|
||||
public ConfigurationPageType ConfigurationPageType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the plugin id.
|
||||
/// </summary>
|
||||
/// <value>The plugin id.</value>
|
||||
public string PluginId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable SA1402
|
||||
#pragma warning disable SA1649
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -20,7 +25,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace MediaBrowser.WebDashboard.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Class GetDashboardConfigurationPages
|
||||
/// Class GetDashboardConfigurationPages.
|
||||
/// </summary>
|
||||
[Route("/web/ConfigurationPages", "GET")]
|
||||
public class GetDashboardConfigurationPages : IReturn<List<ConfigurationPageInfo>>
|
||||
@@ -30,11 +35,12 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
/// </summary>
|
||||
/// <value>The type of the page.</value>
|
||||
public ConfigurationPageType? PageType { get; set; }
|
||||
|
||||
public bool? EnableInMainMenu { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class GetDashboardConfigurationPage
|
||||
/// Class GetDashboardConfigurationPage.
|
||||
/// </summary>
|
||||
[Route("/web/ConfigurationPage", "GET")]
|
||||
public class GetDashboardConfigurationPage
|
||||
@@ -58,7 +64,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class GetDashboardResource
|
||||
/// Class GetDashboardResource.
|
||||
/// </summary>
|
||||
[Route("/web/{ResourceName*}", "GET", IsHidden = true)]
|
||||
public class GetDashboardResource
|
||||
@@ -68,6 +74,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string ResourceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the V.
|
||||
/// </summary>
|
||||
@@ -81,7 +88,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class DashboardService
|
||||
/// Class DashboardService.
|
||||
/// </summary>
|
||||
public class DashboardService : IService, IRequiresRequest
|
||||
{
|
||||
@@ -96,46 +103,38 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
/// </summary>
|
||||
/// <value>The HTTP result factory.</value>
|
||||
private readonly IHttpResultFactory _resultFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the request context.
|
||||
/// </summary>
|
||||
/// <value>The request context.</value>
|
||||
public IRequest Request { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The _app host
|
||||
/// </summary>
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
|
||||
/// <summary>
|
||||
/// The _server configuration manager
|
||||
/// </summary>
|
||||
private readonly IServerConfigurationManager _serverConfigurationManager;
|
||||
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private IResourceFileManager _resourceFileManager;
|
||||
private readonly IConfiguration _appConfig;
|
||||
private readonly IServerConfigurationManager _serverConfigurationManager;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IResourceFileManager _resourceFileManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DashboardService" /> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="appConfig">The application configuration.</param>
|
||||
/// <param name="resourceFileManager">The resource file manager.</param>
|
||||
/// <param name="serverConfigurationManager">The server configuration manager.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="resultFactory">The result factory.</param>
|
||||
public DashboardService(
|
||||
ILogger<DashboardService> logger,
|
||||
IServerApplicationHost appHost,
|
||||
IConfiguration appConfig,
|
||||
IResourceFileManager resourceFileManager,
|
||||
IServerConfigurationManager serverConfigurationManager,
|
||||
IFileSystem fileSystem,
|
||||
ILogger<DashboardService> logger,
|
||||
IHttpResultFactory resultFactory,
|
||||
IConfiguration appConfig)
|
||||
IHttpResultFactory resultFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_appHost = appHost;
|
||||
_appConfig = appConfig;
|
||||
_resourceFileManager = resourceFileManager;
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
_fileSystem = fileSystem;
|
||||
_logger = logger;
|
||||
_resultFactory = resultFactory;
|
||||
_resourceFileManager = resourceFileManager;
|
||||
_appConfig = appConfig;
|
||||
|
||||
// Validate web content path
|
||||
string webContentPath = DashboardUIPath;
|
||||
@@ -149,6 +148,12 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the request context.
|
||||
/// </summary>
|
||||
/// <value>The request context.</value>
|
||||
public IRequest Request { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the directory containing the static web interface content, or null if the server is not
|
||||
/// hosting the static web content.
|
||||
@@ -171,6 +176,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||
public object Get(GetFavIcon request)
|
||||
{
|
||||
return Get(new GetDashboardResource
|
||||
@@ -184,6 +190,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||
public Task<object> Get(GetDashboardConfigurationPage request)
|
||||
{
|
||||
IPlugin plugin = null;
|
||||
@@ -208,7 +215,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
stream = plugin.GetType().Assembly.GetManifestResourceStream(altPage.Item1.EmbeddedResourcePath);
|
||||
|
||||
isJs = string.Equals(Path.GetExtension(altPage.Item1.EmbeddedResourcePath), ".js", StringComparison.OrdinalIgnoreCase);
|
||||
isTemplate = altPage.Item1.EmbeddedResourcePath.EndsWith(".template.html");
|
||||
isTemplate = altPage.Item1.EmbeddedResourcePath.EndsWith(".template.html", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +263,6 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
// Don't allow a failing plugin to fail them all
|
||||
var configPages = pages.Select(p =>
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
return new ConfigurationPageInfo(p);
|
||||
@@ -307,6 +313,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
return GetPluginPages(plugin).Select(i => new ConfigurationPageInfo(plugin, i.Item1));
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||
public object Get(GetRobotsTxt request)
|
||||
{
|
||||
return Get(new GetDashboardResource
|
||||
@@ -374,7 +381,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
return await _resultFactory.GetStaticResult(Request, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(basePath, path, localizationCulture)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await _resultFactory.GetStaticFileResult(Request, _resourceFileManager.GetResourcePath(basePath, path));
|
||||
return await _resultFactory.GetStaticFileResult(Request, _resourceFileManager.GetResourcePath(basePath, path)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private string GetLocalizationCulture()
|
||||
@@ -421,9 +428,9 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
{
|
||||
Directory.Delete(targetPath, true);
|
||||
}
|
||||
catch (IOException)
|
||||
catch (IOException ex)
|
||||
{
|
||||
|
||||
_logger.LogError(ex, "Error deleting {Path}", targetPath);
|
||||
}
|
||||
|
||||
CopyDirectory(inputPath, targetPath);
|
||||
@@ -431,9 +438,9 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
|
||||
var appVersion = _appHost.ApplicationVersionString;
|
||||
|
||||
await DumpHtml(packageCreator, inputPath, targetPath, mode, appVersion);
|
||||
await DumpHtml(packageCreator, inputPath, targetPath, mode, appVersion).ConfigureAwait(false);
|
||||
|
||||
return "";
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private async Task DumpHtml(PackageCreator packageCreator, string source, string destination, string mode, string appVersion)
|
||||
@@ -456,7 +463,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
using (var stream = await packageCreator.GetResource(resourceVirtualPath, mode, null, appVersion).ConfigureAwait(false))
|
||||
using (var fs = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
await stream.CopyToAsync(fs);
|
||||
await stream.CopyToAsync(fs).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,14 +471,17 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
{
|
||||
Directory.CreateDirectory(destination);
|
||||
|
||||
//Now Create all of the directories
|
||||
// Now Create all of the directories
|
||||
foreach (var dirPath in _fileSystem.GetDirectories(source, true))
|
||||
Directory.CreateDirectory(dirPath.FullName.Replace(source, destination));
|
||||
{
|
||||
Directory.CreateDirectory(dirPath.FullName.Replace(source, destination, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
//Copy all the files & Replaces any files with the same name
|
||||
// Copy all the files & Replaces any files with the same name
|
||||
foreach (var newPath in _fileSystem.GetFiles(source, true))
|
||||
File.Copy(newPath.FullName, newPath.FullName.Replace(source, destination), true);
|
||||
{
|
||||
File.Copy(newPath.FullName, newPath.FullName.Replace(source, destination, StringComparison.Ordinal), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@@ -48,6 +51,11 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
/// <summary>
|
||||
/// Modifies the source HTML stream by adding common meta tags, css and js.
|
||||
/// </summary>
|
||||
/// <param name="isMainIndexPage">True if the stream contains content for the main index page.</param>
|
||||
/// <param name="sourceStream">The stream whose content should be modified.</param>
|
||||
/// <param name="mode">The client mode ('cordova', 'android', etc).</param>
|
||||
/// <param name="appVersion">The application version.</param>
|
||||
/// <param name="localizationCulture">The localization culture.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the async operation to read and modify the input stream.
|
||||
/// The task result contains a stream containing the modified HTML content.
|
||||
@@ -69,30 +77,29 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
{
|
||||
var lang = localizationCulture.Split('-')[0];
|
||||
|
||||
html = html.Replace("<html", "<html data-culture=\"" + localizationCulture + "\" lang=\"" + lang + "\"");
|
||||
html = html.Replace("<html", "<html data-culture=\"" + localizationCulture + "\" lang=\"" + lang + "\"", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
if (isMainIndexPage)
|
||||
{
|
||||
html = html.Replace("<head>", "<head>" + GetMetaTags(mode));
|
||||
html = html.Replace("<head>", "<head>" + GetMetaTags(mode), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
// Disable embedded scripts from plugins. We'll run them later once resources have loaded
|
||||
if (html.IndexOf("<script", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
html = html.Replace("<script", "<!--<script");
|
||||
html = html.Replace("</script>", "</script>-->");
|
||||
html = html.Replace("<script", "<!--<script", StringComparison.Ordinal);
|
||||
html = html.Replace("</script>", "</script>-->", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
if (isMainIndexPage)
|
||||
{
|
||||
html = html.Replace("</body>", GetCommonJavascript(mode, appVersion) + "</body>");
|
||||
html = html.Replace("</body>", GetCommonJavascript(mode, appVersion) + "</body>", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(html);
|
||||
|
||||
return new MemoryStream(bytes);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,11 +132,11 @@ namespace MediaBrowser.WebDashboard.Api
|
||||
builder.Append("<script>");
|
||||
if (!string.IsNullOrWhiteSpace(mode))
|
||||
{
|
||||
builder.AppendFormat("window.appMode='{0}';", mode);
|
||||
builder.AppendFormat(CultureInfo.InvariantCulture, "window.appMode='{0}';", mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendFormat("window.dashboardVersion='{0}';", version);
|
||||
builder.AppendFormat(CultureInfo.InvariantCulture, "window.dashboardVersion='{0}';", version);
|
||||
}
|
||||
|
||||
builder.Append("</script>");
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Code Analyzers-->
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
|
||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -6,24 +8,25 @@ using MediaBrowser.Controller.Plugins;
|
||||
|
||||
namespace MediaBrowser.WebDashboard
|
||||
{
|
||||
public class ServerEntryPoint : IServerEntryPoint
|
||||
public sealed class ServerEntryPoint : IServerEntryPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the list of plugin configuration pages
|
||||
/// </summary>
|
||||
/// <value>The configuration pages.</value>
|
||||
public List<IPluginConfigurationPage> PluginConfigurationPages { get; private set; }
|
||||
|
||||
private readonly IApplicationHost _appHost;
|
||||
|
||||
public static ServerEntryPoint Instance { get; private set; }
|
||||
|
||||
public ServerEntryPoint(IApplicationHost appHost)
|
||||
{
|
||||
_appHost = appHost;
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public static ServerEntryPoint Instance { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of plugin configuration pages.
|
||||
/// </summary>
|
||||
/// <value>The configuration pages.</value>
|
||||
public List<IPluginConfigurationPage> PluginConfigurationPages { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
PluginConfigurationPages = _appHost.GetExports<IPluginConfigurationPage>().ToList();
|
||||
@@ -31,6 +34,7 @@ namespace MediaBrowser.WebDashboard
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user