Pārlūkot izejas kodu

update plugin interfaces

Luke Pulverenti 8 gadi atpakaļ
vecāks
revīzija
4b51233cc8

+ 1 - 1
MediaBrowser.Api/BaseApiService.cs

@@ -17,7 +17,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// <summary>
     /// Class BaseApiService
     /// Class BaseApiService
     /// </summary>
     /// </summary>
-    public class BaseApiService : IHasResultFactory, IRestfulService, IHasSession
+    public class BaseApiService : IHasResultFactory, IService, IHasSession
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the logger.
         /// Gets or sets the logger.

+ 0 - 1
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -208,7 +208,6 @@
     <Compile Include="Net\IHasSession.cs" />
     <Compile Include="Net\IHasSession.cs" />
     <Compile Include="Net\IHttpResultFactory.cs" />
     <Compile Include="Net\IHttpResultFactory.cs" />
     <Compile Include="Net\IHttpServer.cs" />
     <Compile Include="Net\IHttpServer.cs" />
-    <Compile Include="Net\IRestfulService.cs" />
     <Compile Include="Net\IServerManager.cs" />
     <Compile Include="Net\IServerManager.cs" />
     <Compile Include="Net\IServiceRequest.cs" />
     <Compile Include="Net\IServiceRequest.cs" />
     <Compile Include="Net\ISessionContext.cs" />
     <Compile Include="Net\ISessionContext.cs" />

+ 2 - 1
MediaBrowser.Controller/Net/IHttpServer.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using MediaBrowser.Model.Services;
 
 
 namespace MediaBrowser.Controller.Net
 namespace MediaBrowser.Controller.Net
 {
 {
@@ -46,7 +47,7 @@ namespace MediaBrowser.Controller.Net
         /// <summary>
         /// <summary>
         /// Inits this instance.
         /// Inits this instance.
         /// </summary>
         /// </summary>
-        void Init(IEnumerable<IRestfulService> services);
+        void Init(IEnumerable<IService> services);
 
 
         /// <summary>
         /// <summary>
         /// If set, all requests will respond with this message
         /// If set, all requests will respond with this message

+ 0 - 12
MediaBrowser.Controller/Net/IRestfulService.cs

@@ -1,12 +0,0 @@
-using MediaBrowser.Model.Services;
-
-namespace MediaBrowser.Controller.Net
-{
-    /// <summary>
-    /// Interface IRestfulService
-    /// </summary>
-    [Logged]
-    public interface IRestfulService : IService
-    {
-    }
-}

+ 14 - 26
MediaBrowser.Controller/Net/LoggedAttribute.cs

@@ -7,12 +7,20 @@ using MediaBrowser.Model.Services;
 
 
 namespace MediaBrowser.Controller.Net
 namespace MediaBrowser.Controller.Net
 {
 {
-    public class LoggedAttribute : Attribute, IHasRequestFilter
+    public class LoggedAttribute : IRequestFilter
     {
     {
-        public ILogger Logger { get; set; }
-        public IUserManager UserManager { get; set; }
-        public ISessionManager SessionManager { get; set; }
-        public IAuthorizationContext AuthorizationContext { get; set; }
+        public LoggedAttribute(ILogger logger, IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext)
+        {
+            Logger = logger;
+            UserManager = userManager;
+            SessionManager = sessionManager;
+            AuthorizationContext = authorizationContext;
+        }
+
+        public ILogger Logger { get; private set; }
+        public IUserManager UserManager { get; private set; }
+        public ISessionManager SessionManager { get; private set; }
+        public IAuthorizationContext AuthorizationContext { get; private set; }
 
 
         /// <summary>
         /// <summary>
         /// The request filter is executed before the service.
         /// The request filter is executed before the service.
@@ -20,7 +28,7 @@ namespace MediaBrowser.Controller.Net
         /// <param name="request">The http request wrapper</param>
         /// <param name="request">The http request wrapper</param>
         /// <param name="response">The http response wrapper</param>
         /// <param name="response">The http response wrapper</param>
         /// <param name="requestDto">The request DTO</param>
         /// <param name="requestDto">The request DTO</param>
-        public void RequestFilter(IRequest request, IResponse response, object requestDto)
+        public void Filter(IRequest request, IResponse response, object requestDto)
         {
         {
             var serviceRequest = new ServiceRequest(request);
             var serviceRequest = new ServiceRequest(request);
             
             
@@ -51,25 +59,5 @@ namespace MediaBrowser.Controller.Net
                 }
                 }
             }
             }
         }
         }
-
-        /// <summary>
-        /// A new shallow copy of this filter is used on every request.
-        /// </summary>
-        /// <returns>IHasRequestFilter.</returns>
-        public IHasRequestFilter Copy()
-        {
-            return this;
-        }
-
-        /// <summary>
-        /// Order in which Request Filters are executed.
-        /// &lt;0 Executed before global request filters
-        /// &gt;0 Executed after global request filters
-        /// </summary>
-        /// <value>The priority.</value>
-        public int Priority
-        {
-            get { return 0; }
-        }
     }
     }
 }
 }

+ 4 - 0
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -167,6 +167,9 @@
     <Compile Include="Net\EndPointInfo.cs" />
     <Compile Include="Net\EndPointInfo.cs" />
     <Compile Include="Net\HttpResponse.cs" />
     <Compile Include="Net\HttpResponse.cs" />
     <Compile Include="Net\IpAddressInfo.cs" />
     <Compile Include="Net\IpAddressInfo.cs" />
+    <Compile Include="Plugins\IHasWebPages.cs" />
+    <Compile Include="Plugins\PluginPageInfo.cs" />
+    <Compile Include="Reflection\IAssemblyInfo.cs" />
     <Compile Include="Services\ApiMemberAttribute.cs" />
     <Compile Include="Services\ApiMemberAttribute.cs" />
     <Compile Include="Services\IAsyncStreamWriter.cs" />
     <Compile Include="Services\IAsyncStreamWriter.cs" />
     <Compile Include="Services\IHasHeaders.cs" />
     <Compile Include="Services\IHasHeaders.cs" />
@@ -174,6 +177,7 @@
     <Compile Include="Services\IHttpRequest.cs" />
     <Compile Include="Services\IHttpRequest.cs" />
     <Compile Include="Services\IHttpResponse.cs" />
     <Compile Include="Services\IHttpResponse.cs" />
     <Compile Include="Services\IRequest.cs" />
     <Compile Include="Services\IRequest.cs" />
+    <Compile Include="Services\IRequestFilter.cs" />
     <Compile Include="Services\IRequiresRequestStream.cs" />
     <Compile Include="Services\IRequiresRequestStream.cs" />
     <Compile Include="Services\IService.cs" />
     <Compile Include="Services\IService.cs" />
     <Compile Include="Net\MimeTypes.cs" />
     <Compile Include="Net\MimeTypes.cs" />

+ 9 - 0
MediaBrowser.Model/Plugins/IHasWebPages.cs

@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Plugins
+{
+    public interface IHasWebPages
+    {
+        IEnumerable<PluginPageInfo> GetPages();
+    }
+}

+ 9 - 0
MediaBrowser.Model/Plugins/PluginPageInfo.cs

@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Plugins
+{
+    public class PluginPageInfo
+    {
+        public string Name { get; set; }
+
+        public string EmbeddedResourcePath { get; set; }
+    }
+}

+ 10 - 0
MediaBrowser.Model/Reflection/IAssemblyInfo.cs

@@ -0,0 +1,10 @@
+using System;
+using System.IO;
+
+namespace MediaBrowser.Model.Reflection
+{
+    public interface IAssemblyInfo
+    {
+        Stream GetManifestResourceStream(Type type, string resource);
+    }
+}

+ 8 - 0
MediaBrowser.Model/Services/IRequestFilter.cs

@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.Services
+{
+    public interface IRequestFilter
+    {
+        void Filter(IRequest request, IResponse response, object requestDto);
+    }
+}

+ 0 - 3
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -53,10 +53,7 @@
     <Reference Include="System" />
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Net" />
     <Reference Include="System.Net" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
     <Reference Include="System.Xml" />
     <Reference Include="System.Xml" />
     <Reference Include="taglib-sharp, Version=2.1.0.0, Culture=neutral, PublicKeyToken=db62eba44689b5b0, processorArchitecture=MSIL">
     <Reference Include="taglib-sharp, Version=2.1.0.0, Culture=neutral, PublicKeyToken=db62eba44689b5b0, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <SpecificVersion>False</SpecificVersion>

+ 13 - 4
MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -17,9 +17,9 @@ using System.Linq;
 using System.Reflection;
 using System.Reflection;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Security;
 using MediaBrowser.Common.Security;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
@@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         private readonly ILogger _logger;
         private readonly ILogger _logger;
         public IEnumerable<string> UrlPrefixes { get; private set; }
         public IEnumerable<string> UrlPrefixes { get; private set; }
 
 
-        private readonly List<IRestfulService> _restServices = new List<IRestfulService>();
+        private readonly List<IService> _restServices = new List<IService>();
 
 
         private IHttpListener _listener;
         private IHttpListener _listener;
 
 
@@ -49,13 +49,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         private readonly INetworkManager _networkManager;
         private readonly INetworkManager _networkManager;
         private readonly IMemoryStreamProvider _memoryStreamProvider;
         private readonly IMemoryStreamProvider _memoryStreamProvider;
 
 
-        public HttpListenerHost(IApplicationHost applicationHost,
+        private readonly IServerApplicationHost _appHost;
+
+        public HttpListenerHost(IServerApplicationHost applicationHost,
             ILogManager logManager,
             ILogManager logManager,
             IServerConfigurationManager config,
             IServerConfigurationManager config,
             string serviceName,
             string serviceName,
             string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices)
             string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices)
             : base(serviceName, assembliesWithServices)
             : base(serviceName, assembliesWithServices)
         {
         {
+            _appHost = applicationHost;
             DefaultRedirectPath = defaultRedirectPath;
             DefaultRedirectPath = defaultRedirectPath;
             _networkManager = networkManager;
             _networkManager = networkManager;
             _memoryStreamProvider = memoryStreamProvider;
             _memoryStreamProvider = memoryStreamProvider;
@@ -116,6 +119,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             //    }
             //    }
             //});
             //});
 
 
+            var requestFilters = _appHost.GetExports<IRequestFilter>().ToList();
+            foreach (var filter in requestFilters)
+            {
+                HostContext.GlobalRequestFilters.Add(filter.Filter);
+            }
+
             HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
             HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
         }
         }
 
 
@@ -569,7 +578,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// Adds the rest handlers.
         /// Adds the rest handlers.
         /// </summary>
         /// </summary>
         /// <param name="services">The services.</param>
         /// <param name="services">The services.</param>
-        public void Init(IEnumerable<IRestfulService> services)
+        public void Init(IEnumerable<IService> services)
         {
         {
             _restServices.AddRange(services);
             _restServices.AddRange(services);
 
 

+ 5 - 6
MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs

@@ -1,6 +1,5 @@
-using MediaBrowser.Common;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
@@ -18,17 +17,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// Creates the server.
         /// Creates the server.
         /// </summary>
         /// </summary>
         /// <returns>IHttpServer.</returns>
         /// <returns>IHttpServer.</returns>
-        public static IHttpServer CreateServer(IApplicationHost applicationHost,
+        public static IHttpServer CreateServer(IServerApplicationHost applicationHost,
             ILogManager logManager,
             ILogManager logManager,
             IServerConfigurationManager config, 
             IServerConfigurationManager config, 
-            INetworkManager _networkmanager,
+            INetworkManager networkmanager,
             IMemoryStreamProvider streamProvider,
             IMemoryStreamProvider streamProvider,
             string serverName, 
             string serverName, 
             string defaultRedirectpath)
             string defaultRedirectpath)
         {
         {
             LogManager.LogFactory = new ServerLogFactory(logManager);
             LogManager.LogFactory = new ServerLogFactory(logManager);
 
 
-            return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager, streamProvider);
+            return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider);
         }
         }
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs

@@ -5,7 +5,7 @@ using MediaBrowser.Model.Services;
 
 
 namespace MediaBrowser.Server.Implementations.HttpServer
 namespace MediaBrowser.Server.Implementations.HttpServer
 {
 {
-    public class SwaggerService : IHasResultFactory, IRestfulService
+    public class SwaggerService : IHasResultFactory, IService
     {
     {
         private readonly IServerApplicationPaths _appPaths;
         private readonly IServerApplicationPaths _appPaths;
 
 

+ 1 - 0
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -270,6 +270,7 @@
     <Compile Include="Persistence\DataExtensions.cs" />
     <Compile Include="Persistence\DataExtensions.cs" />
     <Compile Include="Persistence\IDbConnector.cs" />
     <Compile Include="Persistence\IDbConnector.cs" />
     <Compile Include="Persistence\MediaStreamColumns.cs" />
     <Compile Include="Persistence\MediaStreamColumns.cs" />
+    <Compile Include="Reflection\AssemblyInfo.cs" />
     <Compile Include="Social\SharingManager.cs" />
     <Compile Include="Social\SharingManager.cs" />
     <Compile Include="Social\SharingRepository.cs" />
     <Compile Include="Social\SharingRepository.cs" />
     <Compile Include="Sorting\StartDateComparer.cs" />
     <Compile Include="Sorting\StartDateComparer.cs" />

+ 14 - 0
MediaBrowser.Server.Implementations/Reflection/AssemblyInfo.cs

@@ -0,0 +1,14 @@
+using System;
+using System.IO;
+using MediaBrowser.Model.Reflection;
+
+namespace MediaBrowser.Server.Implementations.Reflection
+{
+    public class AssemblyInfo : IAssemblyInfo
+    {
+        public Stream GetManifestResourceStream(Type type, string resource)
+        {
+            return type.Assembly.GetManifestResourceStream(resource);
+        }
+    }
+}

+ 5 - 1
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -111,9 +111,12 @@ using MediaBrowser.Model.Activity;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Net;
 using MediaBrowser.Model.News;
 using MediaBrowser.Model.News;
+using MediaBrowser.Model.Reflection;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Social;
 using MediaBrowser.Model.Social;
 using MediaBrowser.Model.Xml;
 using MediaBrowser.Model.Xml;
+using MediaBrowser.Server.Implementations.Reflection;
 using MediaBrowser.Server.Implementations.Xml;
 using MediaBrowser.Server.Implementations.Xml;
 
 
 namespace MediaBrowser.Server.Startup.Common
 namespace MediaBrowser.Server.Startup.Common
@@ -634,6 +637,7 @@ namespace MediaBrowser.Server.Startup.Common
             RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer());
             RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer());
 
 
             RegisterSingleInstance<IXmlReaderSettingsFactory>(new XmlReaderSettingsFactory());
             RegisterSingleInstance<IXmlReaderSettingsFactory>(new XmlReaderSettingsFactory());
+            RegisterSingleInstance<IAssemblyInfo>(new AssemblyInfo());
 
 
             UserDataManager = new UserDataManager(LogManager, ServerConfigurationManager);
             UserDataManager = new UserDataManager(LogManager, ServerConfigurationManager);
             RegisterSingleInstance(UserDataManager);
             RegisterSingleInstance(UserDataManager);
@@ -985,7 +989,7 @@ namespace MediaBrowser.Server.Startup.Common
 
 
             base.FindParts();
             base.FindParts();
 
 
-            HttpServer.Init(GetExports<IRestfulService>(false));
+            HttpServer.Init(GetExports<IService>(false));
 
 
             ServerManager.AddWebSocketListeners(GetExports<IWebSocketListener>(false));
             ServerManager.AddWebSocketListeners(GetExports<IWebSocketListener>(false));
 
 

+ 11 - 1
MediaBrowser.WebDashboard/Api/ConfigurationPageInfo.cs

@@ -1,4 +1,6 @@
-using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Model.Plugins;
 
 
 namespace MediaBrowser.WebDashboard.Api
 namespace MediaBrowser.WebDashboard.Api
 {
 {
@@ -30,5 +32,13 @@ namespace MediaBrowser.WebDashboard.Api
             // Don't use "N" because it needs to match Plugin.Id
             // Don't use "N" because it needs to match Plugin.Id
             PluginId = page.Plugin.Id.ToString();
             PluginId = page.Plugin.Id.ToString();
         }
         }
+
+        public ConfigurationPageInfo(IPlugin plugin, PluginPageInfo page)
+        {
+            Name = page.Name;
+
+            // Don't use "N" because it needs to match Plugin.Id
+            PluginId = plugin.Id.ToString();
+        }
     }
     }
 }
 }

+ 57 - 5
MediaBrowser.WebDashboard/Api/DashboardService.cs

@@ -12,8 +12,11 @@ using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using MediaBrowser.Common.Plugins;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Plugins;
+using MediaBrowser.Model.Reflection;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
 
 
 namespace MediaBrowser.WebDashboard.Api
 namespace MediaBrowser.WebDashboard.Api
@@ -76,7 +79,7 @@ namespace MediaBrowser.WebDashboard.Api
     /// <summary>
     /// <summary>
     /// Class DashboardService
     /// Class DashboardService
     /// </summary>
     /// </summary>
-    public class DashboardService : IRestfulService, IHasResultFactory
+    public class DashboardService : IService, IHasResultFactory
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the logger.
         /// Gets or sets the logger.
@@ -109,6 +112,7 @@ namespace MediaBrowser.WebDashboard.Api
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
         private readonly ILocalizationManager _localization;
         private readonly ILocalizationManager _localization;
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IJsonSerializer _jsonSerializer;
+        private readonly IAssemblyInfo _assemblyInfo;
 
 
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="DashboardService" /> class.
         /// Initializes a new instance of the <see cref="DashboardService" /> class.
@@ -116,13 +120,14 @@ namespace MediaBrowser.WebDashboard.Api
         /// <param name="appHost">The app host.</param>
         /// <param name="appHost">The app host.</param>
         /// <param name="serverConfigurationManager">The server configuration manager.</param>
         /// <param name="serverConfigurationManager">The server configuration manager.</param>
         /// <param name="fileSystem">The file system.</param>
         /// <param name="fileSystem">The file system.</param>
-        public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer)
+        public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, IAssemblyInfo assemblyInfo)
         {
         {
             _appHost = appHost;
             _appHost = appHost;
             _serverConfigurationManager = serverConfigurationManager;
             _serverConfigurationManager = serverConfigurationManager;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
             _localization = localization;
             _localization = localization;
             _jsonSerializer = jsonSerializer;
             _jsonSerializer = jsonSerializer;
+            _assemblyInfo = assemblyInfo;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -132,9 +137,32 @@ namespace MediaBrowser.WebDashboard.Api
         /// <returns>System.Object.</returns>
         /// <returns>System.Object.</returns>
         public Task<object> Get(GetDashboardConfigurationPage request)
         public Task<object> Get(GetDashboardConfigurationPage request)
         {
         {
-            var page = ServerEntryPoint.Instance.PluginConfigurationPages.First(p => p.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
+            IPlugin plugin = null;
+            Stream stream = null;
 
 
-            return ResultFactory.GetStaticResult(Request, page.Plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml("dummy.html", page.GetHtmlStream(), null, _appHost.ApplicationVersion.ToString(), null, false));
+            var page = ServerEntryPoint.Instance.PluginConfigurationPages.FirstOrDefault(p => string.Equals(p.Name, request.Name, StringComparison.OrdinalIgnoreCase));
+            if (page != null)
+            {
+                plugin = page.Plugin;
+                stream = page.GetHtmlStream();
+            }
+
+            if (plugin == null)
+            {
+                var altPage = GetPluginPages().FirstOrDefault(p => string.Equals(p.Item1.Name, request.Name, StringComparison.OrdinalIgnoreCase));
+                if (altPage != null)
+                {
+                    plugin = altPage.Item2;
+                    stream = _assemblyInfo.GetManifestResourceStream(plugin.GetType(), altPage.Item1.EmbeddedResourcePath);
+                }
+            }
+
+            if (plugin != null && stream != null)
+            {
+                return ResultFactory.GetStaticResult(Request, plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml("dummy.html", stream, null, _appHost.ApplicationVersion.ToString(), null, false));
+            }
+
+            throw new ResourceNotFoundException();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -162,7 +190,7 @@ namespace MediaBrowser.WebDashboard.Api
 
 
             if (request.PageType.HasValue)
             if (request.PageType.HasValue)
             {
             {
-                pages = pages.Where(p => p.ConfigurationPageType == request.PageType.Value);
+                pages = pages.Where(p => p.ConfigurationPageType == request.PageType.Value).ToList();
             }
             }
 
 
             // Don't allow a failing plugin to fail them all
             // Don't allow a failing plugin to fail them all
@@ -182,9 +210,33 @@ namespace MediaBrowser.WebDashboard.Api
                 .Where(i => i != null)
                 .Where(i => i != null)
                 .ToList();
                 .ToList();
 
 
+            configPages.AddRange(_appHost.Plugins.SelectMany(GetConfigPages));
+
             return ResultFactory.GetOptimizedResult(Request, configPages);
             return ResultFactory.GetOptimizedResult(Request, configPages);
         }
         }
 
 
+        private IEnumerable<Tuple<PluginPageInfo, IPlugin>> GetPluginPages()
+        {
+            return _appHost.Plugins.SelectMany(GetPluginPages);
+        }
+
+        private IEnumerable<Tuple<PluginPageInfo, IPlugin>> GetPluginPages(IPlugin plugin)
+        {
+            var hasConfig = plugin as IHasWebPages;
+
+            if (hasConfig == null)
+            {
+                return new List<Tuple<PluginPageInfo, IPlugin>>();
+            }
+
+            return hasConfig.GetPages().Select(i => new Tuple<PluginPageInfo, IPlugin>(i, plugin));
+        }
+
+        private IEnumerable<ConfigurationPageInfo> GetConfigPages(IPlugin plugin)
+        {
+            return GetPluginPages(plugin).Select(i => new ConfigurationPageInfo(plugin, i.Item1));
+        }
+
         public object Get(GetRobotsTxt request)
         public object Get(GetRobotsTxt request)
         {
         {
             return Get(new GetDashboardResource
             return Get(new GetDashboardResource

+ 3 - 2
MediaBrowser.WebDashboard/ServerEntryPoint.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common;
 using MediaBrowser.Common;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Plugins;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Linq;
 
 
 namespace MediaBrowser.WebDashboard
 namespace MediaBrowser.WebDashboard
 {
 {
@@ -10,7 +11,7 @@ namespace MediaBrowser.WebDashboard
         /// Gets the list of plugin configuration pages
         /// Gets the list of plugin configuration pages
         /// </summary>
         /// </summary>
         /// <value>The configuration pages.</value>
         /// <value>The configuration pages.</value>
-        public IEnumerable<IPluginConfigurationPage> PluginConfigurationPages { get; private set; }
+        public List<IPluginConfigurationPage> PluginConfigurationPages { get; private set; }
 
 
         private readonly IApplicationHost _appHost;
         private readonly IApplicationHost _appHost;
 
 
@@ -24,7 +25,7 @@ namespace MediaBrowser.WebDashboard
 
 
         public void Run()
         public void Run()
         {
         {
-            PluginConfigurationPages = _appHost.GetExports<IPluginConfigurationPage>();
+            PluginConfigurationPages = _appHost.GetExports<IPluginConfigurationPage>().ToList();
         }
         }
 
 
         public void Dispose()
         public void Dispose()

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.676</version>
+        <version>3.0.680</version>
         <title>Emby.Common.Internal</title>
         <title>Emby.Common.Internal</title>
         <authors>Luke</authors>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
         <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.676" />
+            <dependency id="MediaBrowser.Common" version="3.0.680" />
             <dependency id="NLog" version="4.3.8" />
             <dependency id="NLog" version="4.3.8" />
             <dependency id="SimpleInjector" version="3.2.2" />
             <dependency id="SimpleInjector" version="3.2.2" />
         </dependencies>
         </dependencies>

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Common</id>
         <id>MediaBrowser.Common</id>
-        <version>3.0.676</version>
+        <version>3.0.680</version>
         <title>Emby.Common</title>
         <title>Emby.Common</title>
         <authors>Emby Team</authors>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>

+ 3 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Server.Core</id>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.676</version>
+        <version>3.0.680</version>
         <title>Emby.Server.Core</title>
         <title>Emby.Server.Core</title>
         <authors>Emby Team</authors>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,10 +12,11 @@
         <description>Contains core components required to build plugins for Emby Server.</description>
         <description>Contains core components required to build plugins for Emby Server.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.676" />
+            <dependency id="MediaBrowser.Common" version="3.0.680" />
         </dependencies>
         </dependencies>
     </metadata>
     </metadata>
     <files>
     <files>
         <file src="dlls\MediaBrowser.Controller.dll" target="lib\net45\MediaBrowser.Controller.dll" />
         <file src="dlls\MediaBrowser.Controller.dll" target="lib\net45\MediaBrowser.Controller.dll" />
+        <file src="dlls\MediaBrowser.Controller.dll" target="lib\portable-net45+win8+wpa81\MediaBrowser.Controller.dll" />
     </files>
     </files>
 </package>
 </package>