소스 검색

rework result factory

Luke Pulverenti 8 년 전
부모
커밋
227dd0a42d
83개의 변경된 파일717개의 추가작업 그리고 813개의 파일을 삭제
  1. 5 4
      Emby.Server.Implementations/HttpServer/SwaggerService.cs
  2. 18 18
      Emby.Server.sln
  3. 5 2
      MediaBrowser.Api/ApiEntryPoint.cs
  4. 21 22
      MediaBrowser.Api/BaseApiService.cs
  5. 4 2
      MediaBrowser.Api/ConnectService.cs
  6. 5 2
      MediaBrowser.Api/GamesService.cs
  7. 8 6
      MediaBrowser.Api/Images/ImageByNameService.cs
  8. 5 3
      MediaBrowser.Api/Images/ImageService.cs
  9. 9 29
      MediaBrowser.Api/Library/LibraryService.cs
  10. 15 11
      MediaBrowser.Api/LiveTv/LiveTvService.cs
  11. 5 3
      MediaBrowser.Api/Movies/CollectionService.cs
  12. 5 3
      MediaBrowser.Api/Movies/MoviesService.cs
  13. 4 6
      MediaBrowser.Api/Movies/TrailersService.cs
  14. 5 3
      MediaBrowser.Api/Music/AlbumsService.cs
  15. 4 2
      MediaBrowser.Api/Music/InstantMixService.cs
  16. 4 1
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  17. 5 5
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  18. 2 2
      MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
  19. 5 4
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  20. 5 3
      MediaBrowser.Api/Playback/MediaInfoService.cs
  21. 5 4
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  22. 1 1
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  23. 2 2
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  24. 4 2
      MediaBrowser.Api/PlaylistService.cs
  25. 12 10
      MediaBrowser.Api/Session/SessionsService.cs
  26. 5 3
      MediaBrowser.Api/Social/SharingService.cs
  27. 4 2
      MediaBrowser.Api/Subtitles/SubtitleService.cs
  28. 4 2
      MediaBrowser.Api/Sync/SyncService.cs
  29. 8 6
      MediaBrowser.Api/TvShowsService.cs
  30. 6 14
      MediaBrowser.Api/UserLibrary/ArtistsService.cs
  31. 6 3
      MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
  32. 6 7
      MediaBrowser.Api/UserLibrary/GameGenresService.cs
  33. 6 7
      MediaBrowser.Api/UserLibrary/GenresService.cs
  34. 4 2
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  35. 6 7
      MediaBrowser.Api/UserLibrary/MusicGenresService.cs
  36. 6 14
      MediaBrowser.Api/UserLibrary/PersonsService.cs
  37. 11 7
      MediaBrowser.Api/UserLibrary/PlaystateService.cs
  38. 6 7
      MediaBrowser.Api/UserLibrary/StudiosService.cs
  39. 11 9
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  40. 6 3
      MediaBrowser.Api/UserLibrary/UserViewsService.cs
  41. 6 7
      MediaBrowser.Api/UserLibrary/YearsService.cs
  42. 12 10
      MediaBrowser.Api/UserService.cs
  43. 4 2
      MediaBrowser.Api/VideosService.cs
  44. 0 2
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  45. 0 12
      MediaBrowser.Controller/Net/IHasAuthorization.cs
  46. 0 12
      MediaBrowser.Controller/Net/IHasSession.cs
  47. 5 0
      MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
  48. 1 1
      MediaBrowser.Model/Serialization/IXmlSerializer.cs
  49. 0 44
      MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs
  50. 51 51
      MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
  51. 152 6
      MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
  52. 5 2
      MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
  53. 24 8
      MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
  54. 0 4
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  55. 1 20
      MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
  56. 17 13
      MediaBrowser.Server.Mono/Native/MonoApp.cs
  57. 0 45
      MediaBrowser.Server.Mono/Native/NativeApp.cs
  58. 1 1
      MediaBrowser.Server.Mono/Program.cs
  59. 2 2
      MediaBrowser.Server.Startup.Common/ApplicationHost.cs
  60. 20 4
      MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
  61. 5 4
      MediaBrowser.Server.Startup.Common/Networking/NetworkManager.cs
  62. 1 1
      MediaBrowser.Server.Startup.Common/Security/ASN1.cs
  63. 5 4
      MediaBrowser.Server.Startup.Common/Security/ASN1Convert.cs
  64. 2 2
      MediaBrowser.Server.Startup.Common/Security/BitConverterLE.cs
  65. 1 2
      MediaBrowser.Server.Startup.Common/Security/CertificateGenerator.cs
  66. 2 1
      MediaBrowser.Server.Startup.Common/Security/CryptoConvert.cs
  67. 6 5
      MediaBrowser.Server.Startup.Common/Security/PKCS1.cs
  68. 2 1
      MediaBrowser.Server.Startup.Common/Security/PKCS12.cs
  69. 2 1
      MediaBrowser.Server.Startup.Common/Security/PKCS7.cs
  70. 2 1
      MediaBrowser.Server.Startup.Common/Security/PKCS8.cs
  71. 75 0
      MediaBrowser.Server.Startup.Common/Security/PfxGenerator.cs
  72. 8 7
      MediaBrowser.Server.Startup.Common/Security/X501Name.cs
  73. 3 2
      MediaBrowser.Server.Startup.Common/Security/X509Builder.cs
  74. 2 1
      MediaBrowser.Server.Startup.Common/Security/X509Certificate.cs
  75. 5 4
      MediaBrowser.Server.Startup.Common/Security/X509CertificateBuilder.cs
  76. 3 2
      MediaBrowser.Server.Startup.Common/Security/X509CertificateCollection.cs
  77. 3 2
      MediaBrowser.Server.Startup.Common/Security/X509Extension.cs
  78. 3 2
      MediaBrowser.Server.Startup.Common/Security/X509Extensions.cs
  79. 14 13
      MediaBrowser.Server.Startup.Common/Security/X520Attributes.cs
  80. 0 1
      MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
  81. 0 244
      MediaBrowser.ServerApplication/Networking/CertificateGenerator.cs
  82. 2 14
      MediaBrowser.ServerApplication/Networking/NetworkManager.cs
  83. 12 10
      MediaBrowser.WebDashboard/Api/DashboardService.cs

+ 5 - 4
Emby.Server.Implementations/HttpServer/SwaggerService.cs

@@ -6,15 +6,16 @@ using MediaBrowser.Model.Services;
 
 namespace Emby.Server.Implementations.HttpServer
 {
-    public class SwaggerService : IHasResultFactory, IService
+    public class SwaggerService : IService, IRequiresRequest
     {
         private readonly IServerApplicationPaths _appPaths;
         private readonly IFileSystem _fileSystem;
 
-        public SwaggerService(IServerApplicationPaths appPaths, IFileSystem fileSystem)
+        public SwaggerService(IServerApplicationPaths appPaths, IFileSystem fileSystem, IHttpResultFactory resultFactory)
         {
             _appPaths = appPaths;
             _fileSystem = fileSystem;
+            _resultFactory = resultFactory;
         }
 
         /// <summary>
@@ -28,14 +29,14 @@ namespace Emby.Server.Implementations.HttpServer
 
             var requestedFile = Path.Combine(swaggerDirectory, request.ResourceName.Replace('/', _fileSystem.DirectorySeparatorChar));
 
-            return ResultFactory.GetStaticFileResult(Request, requestedFile).Result;
+            return _resultFactory.GetStaticFileResult(Request, requestedFile).Result;
         }
 
         /// <summary>
         /// Gets or sets the result factory.
         /// </summary>
         /// <value>The result factory.</value>
-        public IHttpResultFactory ResultFactory { get; set; }
+        private readonly IHttpResultFactory _resultFactory;
 
         /// <summary>
         /// Gets or sets the request context.

+ 18 - 18
Emby.Server.sln

@@ -36,10 +36,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Emby.Common.Implementations
 EndProject
 Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Mono.Nat", "Mono.Nat\Mono.Nat.xproj", "{0A82260B-4C22-4FD2-869A-E510044E3502}"
 EndProject
-Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RSSDP", "RSSDP\RSSDP.xproj", "{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}"
-EndProject
-Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.xproj", "{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"
@@ -48,6 +44,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{D08B8079-08B3-48F2-83C4-E9CCCE48AFF1}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -133,18 +133,6 @@ Global
 		{0A82260B-4C22-4FD2-869A-E510044E3502}.Release Mono|Any CPU.Build.0 = Release|Any CPU
 		{0A82260B-4C22-4FD2-869A-E510044E3502}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0A82260B-4C22-4FD2-869A-E510044E3502}.Release|Any CPU.Build.0 = Release|Any CPU
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}.Release Mono|Any CPU.Build.0 = Release|Any CPU
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55}.Release|Any CPU.Build.0 = Release|Any CPU
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release Mono|Any CPU.Build.0 = Release|Any CPU
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release|Any CPU.Build.0 = Release|Any CPU
 		{89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
@@ -169,6 +157,18 @@ Global
 		{D08B8079-08B3-48F2-83C4-E9CCCE48AFF1}.Release Mono|Any CPU.Build.0 = Release|Any CPU
 		{D08B8079-08B3-48F2-83C4-E9CCCE48AFF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{D08B8079-08B3-48F2-83C4-E9CCCE48AFF1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -187,11 +187,11 @@ Global
 		{4A4402D4-E910-443B-B8FC-2C18286A2CA0} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 		{5A27010A-09C6-4E86-93EA-437484C10917} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 		{0A82260B-4C22-4FD2-869A-E510044E3502} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
-		{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
-		{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 		{89AB4548-770D-41FD-A891-8DAFF44F452C} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 		{D08B8079-08B3-48F2-83C4-E9CCCE48AFF1} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
+		{21002819-C39A-4D3E-BE83-2A276A77FB1F} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
+		{805844AB-E92F-45E6-9D99-4F6D48D129A5} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
 	EndGlobalSection
 EndGlobal

+ 5 - 2
MediaBrowser.Api/ApiEntryPoint.cs

@@ -16,6 +16,7 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Diagnostics;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Dto;
@@ -37,7 +38,8 @@ namespace MediaBrowser.Api
         /// Gets or sets the logger.
         /// </summary>
         /// <value>The logger.</value>
-        private ILogger Logger { get; set; }
+        internal ILogger Logger { get; private set; }
+        internal IHttpResultFactory ResultFactory { get; private set; }
 
         /// <summary>
         /// The application paths
@@ -66,7 +68,7 @@ namespace MediaBrowser.Api
         /// <param name="config">The configuration.</param>
         /// <param name="fileSystem">The file system.</param>
         /// <param name="mediaSourceManager">The media source manager.</param>
-        public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager, ITimerFactory timerFactory, IProcessFactory processFactory)
+        public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager, ITimerFactory timerFactory, IProcessFactory processFactory, IHttpResultFactory resultFactory)
         {
             Logger = logger;
             _sessionManager = sessionManager;
@@ -75,6 +77,7 @@ namespace MediaBrowser.Api
             _mediaSourceManager = mediaSourceManager;
             TimerFactory = timerFactory;
             ProcessFactory = processFactory;
+            ResultFactory = resultFactory;
 
             Instance = this;
             _sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress;

+ 21 - 22
MediaBrowser.Api/BaseApiService.cs

@@ -17,19 +17,31 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class BaseApiService
     /// </summary>
-    public class BaseApiService : IHasResultFactory, IService, IHasSession
+    public class BaseApiService : IService, IRequiresRequest
     {
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
         /// <value>The logger.</value>
-        public ILogger Logger { get; set; }
+        public ILogger Logger
+        {
+            get
+            {
+                return ApiEntryPoint.Instance.Logger;
+            }
+        }
 
         /// <summary>
         /// Gets or sets the HTTP result factory.
         /// </summary>
         /// <value>The HTTP result factory.</value>
-        public IHttpResultFactory ResultFactory { get; set; }
+        public IHttpResultFactory ResultFactory
+        {
+            get
+            {
+                return ApiEntryPoint.Instance.ResultFactory;
+            }
+        }
 
         /// <summary>
         /// Gets or sets the request context.
@@ -37,9 +49,6 @@ namespace MediaBrowser.Api
         /// <value>The request context.</value>
         public IRequest Request { get; set; }
 
-        public ISessionContext SessionContext { get; set; }
-        public IAuthorizationContext AuthorizationContext { get; set; }
-
         public string GetHeader(string name)
         {
             return Request.Headers[name];
@@ -57,9 +66,9 @@ namespace MediaBrowser.Api
             return ResultFactory.GetOptimizedResult(Request, result);
         }
 
-        protected void AssertCanUpdateUser(IUserManager userManager, string userId)
+        protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId)
         {
-            var auth = AuthorizationContext.GetAuthorizationInfo(Request);
+            var auth = authContext.GetAuthorizationInfo(Request);
 
             var authenticatedUser = userManager.GetUserById(auth.UserId);
 
@@ -96,9 +105,9 @@ namespace MediaBrowser.Api
         /// Gets the session.
         /// </summary>
         /// <returns>SessionInfo.</returns>
-        protected async Task<SessionInfo> GetSession()
+        protected async Task<SessionInfo> GetSession(ISessionContext sessionContext)
         {
-            var session = await SessionContext.GetSession(Request).ConfigureAwait(false);
+            var session = await sessionContext.GetSession(Request).ConfigureAwait(false);
 
             if (session == null)
             {
@@ -108,21 +117,11 @@ namespace MediaBrowser.Api
             return session;
         }
 
-        /// <summary>
-        /// To the static file result.
-        /// </summary>
-        /// <param name="path">The path.</param>
-        /// <returns>System.Object.</returns>
-        protected object ToStaticFileResult(string path)
-        {
-            return ResultFactory.GetStaticFileResult(Request, path).Result;
-        }
-
-        protected DtoOptions GetDtoOptions(object request)
+        protected DtoOptions GetDtoOptions(IAuthorizationContext authContext, object request)
         {
             var options = new DtoOptions();
 
-            options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+            options.DeviceId = authContext.GetAuthorizationInfo(Request).DeviceId;
 
             var hasFields = request as IHasItemFields;
             if (hasFields != null)

+ 4 - 2
MediaBrowser.Api/ConnectService.cs

@@ -78,11 +78,13 @@ namespace MediaBrowser.Api
     {
         private readonly IConnectManager _connectManager;
         private readonly ISessionManager _sessionManager;
+        private readonly IAuthorizationContext _authContext;
 
-        public ConnectService(IConnectManager connectManager, ISessionManager sessionManager)
+        public ConnectService(IConnectManager connectManager, ISessionManager sessionManager, IAuthorizationContext authContext)
         {
             _connectManager = connectManager;
             _sessionManager = sessionManager;
+            _authContext = authContext;
         }
 
         public object Post(CreateConnectLink request)
@@ -142,7 +144,7 @@ namespace MediaBrowser.Api
                 throw new ResourceNotFoundException();
             }
 
-            var auth = AuthorizationContext.GetAuthorizationInfo(Request);
+            var auth = _authContext.GetAuthorizationInfo(Request);
 
             if (string.IsNullOrWhiteSpace(auth.Client))
             {

+ 5 - 2
MediaBrowser.Api/GamesService.cs

@@ -80,6 +80,8 @@ namespace MediaBrowser.Api
         /// </summary>
         private readonly IDtoService _dtoService;
 
+        private readonly IAuthorizationContext _authContext;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="GamesService" /> class.
         /// </summary>
@@ -88,13 +90,14 @@ namespace MediaBrowser.Api
         /// <param name="libraryManager">The library manager.</param>
         /// <param name="itemRepo">The item repo.</param>
         /// <param name="dtoService">The dto service.</param>
-        public GamesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
+        public GamesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userDataRepository = userDataRepository;
             _libraryManager = libraryManager;
             _itemRepo = itemRepo;
             _dtoService = dtoService;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -200,7 +203,7 @@ namespace MediaBrowser.Api
                 (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
                 _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
             {

+ 8 - 6
MediaBrowser.Api/Images/ImageByNameService.cs

@@ -102,15 +102,17 @@ namespace MediaBrowser.Api.Images
         private readonly IServerApplicationPaths _appPaths;
 
         private readonly IFileSystem _fileSystem;
+        private readonly IHttpResultFactory _resultFactory;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageByNameService" /> class.
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
-        public ImageByNameService(IServerApplicationPaths appPaths, IFileSystem fileSystem)
+        public ImageByNameService(IServerApplicationPaths appPaths, IFileSystem fileSystem, IHttpResultFactory resultFactory)
         {
             _appPaths = appPaths;
             _fileSystem = fileSystem;
+            _resultFactory = resultFactory;
         }
 
         public object Get(GetMediaInfoImages request)
@@ -187,7 +189,7 @@ namespace MediaBrowser.Api.Images
 
 			var path = paths.FirstOrDefault(_fileSystem.FileExists) ?? paths.FirstOrDefault();
 
-            return ToStaticFileResult(path);
+            return _resultFactory.GetStaticFileResult(Request, path);
         }
 
         /// <summary>
@@ -207,7 +209,7 @@ namespace MediaBrowser.Api.Images
 
                 if (!string.IsNullOrEmpty(path))
                 {
-                    return ToStaticFileResult(path);
+                    return _resultFactory.GetStaticFileResult(Request, path);
                 }
             }
 
@@ -224,7 +226,7 @@ namespace MediaBrowser.Api.Images
 
                 if (!string.IsNullOrEmpty(path))
                 {
-                    return ToStaticFileResult(path);
+                    return _resultFactory.GetStaticFileResult(Request, path);
                 }
             }
 
@@ -247,7 +249,7 @@ namespace MediaBrowser.Api.Images
 
                 if (!string.IsNullOrEmpty(path))
                 {
-                    return ToStaticFileResult(path);
+                    return _resultFactory.GetStaticFileResult(Request, path);
                 }
             }
 
@@ -263,7 +265,7 @@ namespace MediaBrowser.Api.Images
 
                 if (!string.IsNullOrEmpty(path))
                 {
-                    return ToStaticFileResult(path);
+                    return _resultFactory.GetStaticFileResult(Request, path);
                 }
             }
 

+ 5 - 3
MediaBrowser.Api/Images/ImageService.cs

@@ -236,11 +236,12 @@ namespace MediaBrowser.Api.Images
         private readonly IItemRepository _itemRepo;
         private readonly IImageProcessor _imageProcessor;
         private readonly IFileSystem _fileSystem;
+        private readonly IAuthorizationContext _authContext;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageService" /> class.
         /// </summary>
-        public ImageService(IUserManager userManager, ILibraryManager libraryManager, IProviderManager providerManager, IItemRepository itemRepo, IImageProcessor imageProcessor, IFileSystem fileSystem)
+        public ImageService(IUserManager userManager, ILibraryManager libraryManager, IProviderManager providerManager, IItemRepository itemRepo, IImageProcessor imageProcessor, IFileSystem fileSystem, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _libraryManager = libraryManager;
@@ -248,6 +249,7 @@ namespace MediaBrowser.Api.Images
             _itemRepo = itemRepo;
             _imageProcessor = imageProcessor;
             _fileSystem = fileSystem;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -425,7 +427,7 @@ namespace MediaBrowser.Api.Images
         public void Post(PostUserImage request)
         {
             var userId = GetPathValue(1);
-            AssertCanUpdateUser(_userManager, userId);
+            AssertCanUpdateUser(_authContext, _userManager, userId);
 
             request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
 
@@ -460,7 +462,7 @@ namespace MediaBrowser.Api.Images
         public void Delete(DeleteUserImage request)
         {
             var userId = request.Id;
-            AssertCanUpdateUser(_userManager, userId);
+            AssertCanUpdateUser(_authContext, _userManager, userId);
 
             var item = _userManager.GetUserById(userId);
 

+ 9 - 29
MediaBrowser.Api/Library/LibraryService.cs

@@ -323,13 +323,9 @@ namespace MediaBrowser.Api.Library
 
             if (item is Game)
             {
-                return new GamesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
+                return new GamesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _authContext)
                 {
-                    AuthorizationContext = AuthorizationContext,
-                    Logger = Logger,
                     Request = Request,
-                    SessionContext = SessionContext,
-                    ResultFactory = ResultFactory
 
                 }.Get(new GetSimilarGames
                 {
@@ -341,13 +337,9 @@ namespace MediaBrowser.Api.Library
             }
             if (item is MusicAlbum)
             {
-                return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
+                return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _authContext)
                 {
-                    AuthorizationContext = AuthorizationContext,
-                    Logger = Logger,
                     Request = Request,
-                    SessionContext = SessionContext,
-                    ResultFactory = ResultFactory
 
                 }.Get(new GetSimilarAlbums
                 {
@@ -360,13 +352,9 @@ namespace MediaBrowser.Api.Library
             }
             if (item is MusicArtist)
             {
-                return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
+                return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _authContext)
                 {
-                    AuthorizationContext = AuthorizationContext,
-                    Logger = Logger,
                     Request = Request,
-                    SessionContext = SessionContext,
-                    ResultFactory = ResultFactory
 
                 }.Get(new GetSimilarArtists
                 {
@@ -381,13 +369,9 @@ namespace MediaBrowser.Api.Library
 
             if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
             {
-                return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _config)
+                return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _config, _authContext)
                 {
-                    AuthorizationContext = AuthorizationContext,
-                    Logger = Logger,
                     Request = Request,
-                    SessionContext = SessionContext,
-                    ResultFactory = ResultFactory
 
                 }.Get(new GetSimilarMovies
                 {
@@ -400,13 +384,9 @@ namespace MediaBrowser.Api.Library
 
             if (item is Series || (program != null && program.IsSeries))
             {
-                return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager)
+                return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager, _authContext)
                 {
-                    AuthorizationContext = AuthorizationContext,
-                    Logger = Logger,
                     Request = Request,
-                    SessionContext = SessionContext,
-                    ResultFactory = ResultFactory
 
                 }.Get(new GetSimilarShows
                 {
@@ -431,7 +411,7 @@ namespace MediaBrowser.Api.Library
                 items = items.Where(i => i.IsHidden == val).ToList();
             }
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = new ItemsResult
             {
@@ -612,7 +592,7 @@ namespace MediaBrowser.Api.Library
 
             var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             BaseItem parent = item.GetParent();
 
@@ -841,7 +821,7 @@ namespace MediaBrowser.Api.Library
                 item = item.GetParent();
             }
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = item.ThemeSongIds.Select(_libraryManager.GetItemById)
                             .Where(i => i != null)
@@ -885,7 +865,7 @@ namespace MediaBrowser.Api.Library
                 item = item.GetParent();
             }
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = item.ThemeVideoIds.Select(_libraryManager.GetItemById)
                             .Where(i => i != null)

+ 15 - 11
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -695,8 +695,10 @@ namespace MediaBrowser.Api.LiveTv
         private readonly ILibraryManager _libraryManager;
         private readonly IDtoService _dtoService;
         private readonly IFileSystem _fileSystem;
+        private readonly IAuthorizationContext _authContext;
+        private readonly ISessionContext _sessionContext;
 
-        public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IServerConfigurationManager config, IHttpClient httpClient, ILibraryManager libraryManager, IDtoService dtoService, IFileSystem fileSystem)
+        public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IServerConfigurationManager config, IHttpClient httpClient, ILibraryManager libraryManager, IDtoService dtoService, IFileSystem fileSystem, IAuthorizationContext authContext, ISessionContext sessionContext)
         {
             _liveTvManager = liveTvManager;
             _userManager = userManager;
@@ -705,6 +707,8 @@ namespace MediaBrowser.Api.LiveTv
             _libraryManager = libraryManager;
             _dtoService = dtoService;
             _fileSystem = fileSystem;
+            _authContext = authContext;
+            _sessionContext = sessionContext;
         }
 
         public object Get(GetLiveRecordingFile request)
@@ -819,7 +823,7 @@ namespace MediaBrowser.Api.LiveTv
 
         private void AssertUserCanManageLiveTv()
         {
-            var user = SessionContext.GetUser(Request).Result;
+            var user = _sessionContext.GetUser(Request).Result;
 
             if (user == null)
             {
@@ -907,7 +911,7 @@ namespace MediaBrowser.Api.LiveTv
 
             var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
 
-            var options = GetDtoOptions(request);
+            var options = GetDtoOptions(_authContext, request);
             RemoveFields(options);
 
             options.AddCurrentProgram = request.AddCurrentProgram;
@@ -937,7 +941,7 @@ namespace MediaBrowser.Api.LiveTv
 
             var item = _libraryManager.GetItemById(request.Id);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
 
@@ -1002,7 +1006,7 @@ namespace MediaBrowser.Api.LiveTv
                 }
             }
 
-            var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
+            var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None).ConfigureAwait(false);
 
             return ToOptimizedResult(result);
         }
@@ -1023,7 +1027,7 @@ namespace MediaBrowser.Api.LiveTv
                 EnableTotalRecordCount = request.EnableTotalRecordCount
             };
 
-            var result = await _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
+            var result = await _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None).ConfigureAwait(false);
 
             return ToOptimizedResult(result);
         }
@@ -1035,8 +1039,8 @@ namespace MediaBrowser.Api.LiveTv
 
         public async Task<object> Get(GetRecordings request)
         {
-            var options = GetDtoOptions(request);
-            options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+            var options = GetDtoOptions(_authContext, request);
+            options.DeviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
 
             var result = await _liveTvManager.GetRecordings(new RecordingQuery
             {
@@ -1062,8 +1066,8 @@ namespace MediaBrowser.Api.LiveTv
 
         public async Task<object> Get(GetRecordingSeries request)
         {
-            var options = GetDtoOptions(request);
-            options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+            var options = GetDtoOptions(_authContext, request);
+            options.DeviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
 
             var result = await _liveTvManager.GetRecordingSeries(new RecordingQuery
             {
@@ -1087,7 +1091,7 @@ namespace MediaBrowser.Api.LiveTv
             var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
 
             var options = new DtoOptions();
-            options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+            options.DeviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
 
             var result = await _liveTvManager.GetRecording(request.Id, options, CancellationToken.None, user).ConfigureAwait(false);
 

+ 5 - 3
MediaBrowser.Api/Movies/CollectionService.cs

@@ -51,16 +51,18 @@ namespace MediaBrowser.Api.Movies
     {
         private readonly ICollectionManager _collectionManager;
         private readonly IDtoService _dtoService;
+        private readonly IAuthorizationContext _authContext;
 
-        public CollectionService(ICollectionManager collectionManager, IDtoService dtoService)
+        public CollectionService(ICollectionManager collectionManager, IDtoService dtoService, IAuthorizationContext authContext)
         {
             _collectionManager = collectionManager;
             _dtoService = dtoService;
+            _authContext = authContext;
         }
 
         public async Task<object> Post(CreateCollection request)
         {
-            var userId = AuthorizationContext.GetAuthorizationInfo(Request).UserId;
+            var userId = _authContext.GetAuthorizationInfo(Request).UserId;
 
             var parentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
 
@@ -74,7 +76,7 @@ namespace MediaBrowser.Api.Movies
 
             }).ConfigureAwait(false);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dto = _dtoService.GetBaseItemDto(item, dtoOptions);
 

+ 5 - 3
MediaBrowser.Api/Movies/MoviesService.cs

@@ -90,6 +90,7 @@ namespace MediaBrowser.Api.Movies
         private readonly IItemRepository _itemRepo;
         private readonly IDtoService _dtoService;
         private readonly IServerConfigurationManager _config;
+        private readonly IAuthorizationContext _authContext;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="MoviesService" /> class.
@@ -99,7 +100,7 @@ namespace MediaBrowser.Api.Movies
         /// <param name="libraryManager">The library manager.</param>
         /// <param name="itemRepo">The item repo.</param>
         /// <param name="dtoService">The dto service.</param>
-        public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IServerConfigurationManager config)
+        public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IServerConfigurationManager config, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userDataRepository = userDataRepository;
@@ -107,6 +108,7 @@ namespace MediaBrowser.Api.Movies
             _itemRepo = itemRepo;
             _dtoService = dtoService;
             _config = config;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -132,7 +134,7 @@ namespace MediaBrowser.Api.Movies
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             dtoOptions.Fields = request.GetItemFields().ToList();
 
@@ -156,7 +158,7 @@ namespace MediaBrowser.Api.Movies
                 itemTypes.Add(typeof(LiveTvProgram).Name);
             }
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
             {

+ 4 - 6
MediaBrowser.Api/Movies/TrailersService.cs

@@ -39,8 +39,9 @@ namespace MediaBrowser.Api.Movies
         private readonly ICollectionManager _collectionManager;
         private readonly ILocalizationManager _localizationManager;
         private readonly IJsonSerializer _json;
+        private readonly IAuthorizationContext _authContext;
 
-        public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, ICollectionManager collectionManager, ILocalizationManager localizationManager, IJsonSerializer json)
+        public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, ICollectionManager collectionManager, ILocalizationManager localizationManager, IJsonSerializer json, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userDataRepository = userDataRepository;
@@ -49,6 +50,7 @@ namespace MediaBrowser.Api.Movies
             _collectionManager = collectionManager;
             _localizationManager = localizationManager;
             _json = json;
+            _authContext = authContext;
         }
 
         public object Get(Getrailers request)
@@ -58,13 +60,9 @@ namespace MediaBrowser.Api.Movies
 
             getItems.IncludeItemTypes = "Trailer";
 
-            return new ItemsService(_userManager, _libraryManager, _localizationManager, _dtoService)
+            return new ItemsService(_userManager, _libraryManager, _localizationManager, _dtoService, _authContext)
             {
-                AuthorizationContext = AuthorizationContext,
-                Logger = Logger,
                 Request = Request,
-                ResultFactory = ResultFactory,
-                SessionContext = SessionContext
 
             }.Get(getItems);
         }

+ 5 - 3
MediaBrowser.Api/Music/AlbumsService.cs

@@ -40,19 +40,21 @@ namespace MediaBrowser.Api.Music
         private readonly ILibraryManager _libraryManager;
         private readonly IItemRepository _itemRepo;
         private readonly IDtoService _dtoService;
+        private readonly IAuthorizationContext _authContext;
 
-        public AlbumsService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
+        public AlbumsService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userDataRepository = userDataRepository;
             _libraryManager = libraryManager;
             _itemRepo = itemRepo;
             _dtoService = dtoService;
+            _authContext = authContext;
         }
 
         public async Task<object> Get(GetSimilarArtists request)
         {
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = await SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
                 _itemRepo,
@@ -73,7 +75,7 @@ namespace MediaBrowser.Api.Music
         /// <returns>System.Object.</returns>
         public async Task<object> Get(GetSimilarAlbums request)
         {
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = await SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
                 _itemRepo,

+ 4 - 2
MediaBrowser.Api/Music/InstantMixService.cs

@@ -68,13 +68,15 @@ namespace MediaBrowser.Api.Music
         private readonly IDtoService _dtoService;
         private readonly ILibraryManager _libraryManager;
         private readonly IMusicManager _musicManager;
+        private readonly IAuthorizationContext _authContext;
 
-        public InstantMixService(IUserManager userManager, IDtoService dtoService, IMusicManager musicManager, ILibraryManager libraryManager)
+        public InstantMixService(IUserManager userManager, IDtoService dtoService, IMusicManager musicManager, ILibraryManager libraryManager, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _dtoService = dtoService;
             _musicManager = musicManager;
             _libraryManager = libraryManager;
+            _authContext = authContext;
         }
 
         public Task<object> Get(GetInstantMixFromItem request)
@@ -171,7 +173,7 @@ namespace MediaBrowser.Api.Music
                 TotalRecordCount = list.Count
             };
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             result.Items = (await _dtoService.GetBaseItemDtos(list.Take(request.Limit ?? list.Count), dtoOptions, user).ConfigureAwait(false)).ToArray();
 

+ 4 - 1
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -21,6 +21,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Diagnostics;
 
 namespace MediaBrowser.Api.Playback
@@ -71,13 +72,15 @@ namespace MediaBrowser.Api.Playback
 
         public static IServerApplicationHost AppHost;
         public static IHttpClient HttpClient;
+        protected IAuthorizationContext AuthorizationContext { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
         /// </summary>
-        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer)
+        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext)
         {
             JsonSerializer = jsonSerializer;
+            AuthorizationContext = authorizationContext;
             ZipClient = zipClient;
             MediaSourceManager = mediaSourceManager;
             DeviceManager = deviceManager;

+ 5 - 5
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -15,6 +15,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.IO;
 
 namespace MediaBrowser.Api.Playback.Hls
@@ -24,11 +25,6 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public abstract class BaseHlsService : BaseStreamingService
     {
-        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer)
-            : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer)
-        {
-        }
-
         /// <summary>
         /// Gets the audio arguments.
         /// </summary>
@@ -292,5 +288,9 @@ namespace MediaBrowser.Api.Playback.Hls
 
             return isLiveStream;
         }
+
+        public BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
+        {
+        }
     }
 }

+ 2 - 2
MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs

@@ -95,8 +95,8 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class DynamicHlsService : BaseHlsService
     {
-        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, INetworkManager networkManager)
-            : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer)
+
+        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
         {
             NetworkManager = networkManager;
         }

+ 5 - 4
MediaBrowser.Api/Playback/Hls/VideoHlsService.cs

@@ -8,6 +8,7 @@ using MediaBrowser.Model.Serialization;
 using System;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Services;
@@ -24,10 +25,6 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public class VideoHlsService : BaseHlsService
     {
-        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer)
-        {
-        }
-
         public object Get(GetLiveHlsStream request)
         {
             return ProcessRequest(request, true);
@@ -129,5 +126,9 @@ namespace MediaBrowser.Api.Playback.Hls
         {
             return ".ts";
         }
+
+        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
+        {
+        }
     }
 }

+ 5 - 3
MediaBrowser.Api/Playback/MediaInfoService.cs

@@ -72,8 +72,9 @@ namespace MediaBrowser.Api.Playback
         private readonly IMediaEncoder _mediaEncoder;
         private readonly IUserManager _userManager;
         private readonly IJsonSerializer _json;
+        private readonly IAuthorizationContext _authContext;
 
-        public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder, IUserManager userManager, IJsonSerializer json)
+        public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder, IUserManager userManager, IJsonSerializer json, IAuthorizationContext authContext)
         {
             _mediaSourceManager = mediaSourceManager;
             _deviceManager = deviceManager;
@@ -83,6 +84,7 @@ namespace MediaBrowser.Api.Playback
             _mediaEncoder = mediaEncoder;
             _userManager = userManager;
             _json = json;
+            _authContext = authContext;
         }
 
         public object Get(GetBitrateTestBytes request)
@@ -105,7 +107,7 @@ namespace MediaBrowser.Api.Playback
 
         public async Task<object> Post(OpenMediaSource request)
         {
-            var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
+            var authInfo = _authContext.GetAuthorizationInfo(Request);
 
             var result = await _mediaSourceManager.OpenLiveStream(request, true, CancellationToken.None).ConfigureAwait(false);
 
@@ -146,7 +148,7 @@ namespace MediaBrowser.Api.Playback
 
         public async Task<object> Post(GetPostedPlaybackInfo request)
         {
-            var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
+            var authInfo = _authContext.GetAuthorizationInfo(Request);
 
             var profile = request.DeviceProfile;
 

+ 5 - 4
MediaBrowser.Api/Playback/Progressive/AudioService.cs

@@ -11,6 +11,7 @@ using System.Collections.Generic;
 using System.Threading.Tasks;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Services;
 
@@ -34,10 +35,6 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class AudioService : BaseProgressiveStreamingService
     {
-        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, imageProcessor, httpClient)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -97,5 +94,9 @@ namespace MediaBrowser.Api.Playback.Progressive
                 string.Join(" ", audioTranscodeParams.ToArray()),
                 outputPath).Trim();
         }
+
+        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
+        {
+        }
     }
 }

+ 1 - 1
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -29,7 +29,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     {
         protected readonly IImageProcessor ImageProcessor;
 
-        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer)
+        public BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
         {
             ImageProcessor = imageProcessor;
         }

+ 2 - 2
MediaBrowser.Api/Playback/Progressive/VideoService.cs

@@ -12,6 +12,7 @@ using System.IO;
 using System.Threading.Tasks;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Services;
@@ -68,8 +69,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class VideoService : BaseProgressiveStreamingService
     {
-        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient)
-            : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, imageProcessor, httpClient)
+        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
         {
         }
 

+ 4 - 2
MediaBrowser.Api/PlaylistService.cs

@@ -125,13 +125,15 @@ namespace MediaBrowser.Api
         private readonly IDtoService _dtoService;
         private readonly IUserManager _userManager;
         private readonly ILibraryManager _libraryManager;
+        private readonly IAuthorizationContext _authContext;
 
-        public PlaylistService(IDtoService dtoService, IPlaylistManager playlistManager, IUserManager userManager, ILibraryManager libraryManager)
+        public PlaylistService(IDtoService dtoService, IPlaylistManager playlistManager, IUserManager userManager, ILibraryManager libraryManager, IAuthorizationContext authContext)
         {
             _dtoService = dtoService;
             _playlistManager = playlistManager;
             _userManager = userManager;
             _libraryManager = libraryManager;
+            _authContext = authContext;
         }
 
         public void Post(MoveItem request)
@@ -188,7 +190,7 @@ namespace MediaBrowser.Api
                 items = items.Take(request.Limit.Value).ToArray();
             }
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = (await _dtoService.GetBaseItemDtos(items.Select(i => i.Item2), dtoOptions, user).ConfigureAwait(false))
                    .ToArray();

+ 12 - 10
MediaBrowser.Api/Session/SessionsService.cs

@@ -306,6 +306,7 @@ namespace MediaBrowser.Api.Session
         private readonly IAuthorizationContext _authContext;
         private readonly IAuthenticationRepository _authRepo;
         private readonly IDeviceManager _deviceManager;
+        private readonly ISessionContext _sessionContext;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="SessionsService" /> class.
@@ -314,13 +315,14 @@ namespace MediaBrowser.Api.Session
         /// <param name="userManager">The user manager.</param>
         /// <param name="authContext">The authentication context.</param>
         /// <param name="authRepo">The authentication repo.</param>
-        public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo, IDeviceManager deviceManager)
+        public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo, IDeviceManager deviceManager, ISessionContext sessionContext)
         {
             _sessionManager = sessionManager;
             _userManager = userManager;
             _authContext = authContext;
             _authRepo = authRepo;
             _deviceManager = deviceManager;
+            _sessionContext = sessionContext;
         }
 
         public void Delete(RevokeKey request)
@@ -419,7 +421,7 @@ namespace MediaBrowser.Api.Session
                 SeekPositionTicks = request.SeekPositionTicks
             };
 
-            var task = _sessionManager.SendPlaystateCommand(GetSession().Result.Id, request.Id, command, CancellationToken.None);
+            var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
 
             Task.WaitAll(task);
         }
@@ -437,7 +439,7 @@ namespace MediaBrowser.Api.Session
                 ItemType = request.ItemType
             };
 
-            var task = _sessionManager.SendBrowseCommand(GetSession().Result.Id, request.Id, command, CancellationToken.None);
+            var task = _sessionManager.SendBrowseCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
 
             Task.WaitAll(task);
         }
@@ -456,7 +458,7 @@ namespace MediaBrowser.Api.Session
                 name = commandType.ToString();
             }
 
-            var currentSession = GetSession().Result;
+            var currentSession = GetSession(_sessionContext).Result;
 
             var command = new GeneralCommand
             {
@@ -482,7 +484,7 @@ namespace MediaBrowser.Api.Session
                 Text = request.Text
             };
 
-            var task = _sessionManager.SendMessageCommand(GetSession().Result.Id, request.Id, command, CancellationToken.None);
+            var task = _sessionManager.SendMessageCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
 
             Task.WaitAll(task);
         }
@@ -501,14 +503,14 @@ namespace MediaBrowser.Api.Session
                 StartPositionTicks = request.StartPositionTicks
             };
 
-            var task = _sessionManager.SendPlayCommand(GetSession().Result.Id, request.Id, command, CancellationToken.None);
+            var task = _sessionManager.SendPlayCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
 
             Task.WaitAll(task);
         }
 
         public void Post(SendGeneralCommand request)
         {
-            var currentSession = GetSession().Result;
+            var currentSession = GetSession(_sessionContext).Result;
 
             var command = new GeneralCommand
             {
@@ -523,7 +525,7 @@ namespace MediaBrowser.Api.Session
 
         public void Post(SendFullGeneralCommand request)
         {
-            var currentSession = GetSession().Result;
+            var currentSession = GetSession(_sessionContext).Result;
 
             request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null;
 
@@ -546,7 +548,7 @@ namespace MediaBrowser.Api.Session
         {
             if (string.IsNullOrWhiteSpace(request.Id))
             {
-                request.Id = GetSession().Result.Id;
+                request.Id = GetSession(_sessionContext).Result.Id;
             }
             _sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
             {
@@ -570,7 +572,7 @@ namespace MediaBrowser.Api.Session
         {
             if (string.IsNullOrWhiteSpace(request.Id))
             {
-                request.Id = GetSession().Result.Id;
+                request.Id = GetSession(_sessionContext).Result.Id;
             }
             _sessionManager.ReportCapabilities(request.Id, request);
         }

+ 5 - 3
MediaBrowser.Api/Social/SharingService.cs

@@ -66,13 +66,15 @@ namespace MediaBrowser.Api.Social
         private readonly ILibraryManager _libraryManager;
         private readonly IDlnaManager _dlnaManager;
         private readonly IDtoService _dtoService;
+        private readonly IHttpResultFactory _resultFactory;
 
-        public SharingService(ISharingManager sharingManager, IDlnaManager dlnaManager, ILibraryManager libraryManager, IDtoService dtoService)
+        public SharingService(ISharingManager sharingManager, IDlnaManager dlnaManager, ILibraryManager libraryManager, IDtoService dtoService, IHttpResultFactory resultFactory)
         {
             _sharingManager = sharingManager;
             _dlnaManager = dlnaManager;
             _libraryManager = libraryManager;
             _dtoService = dtoService;
+            _resultFactory = resultFactory;
         }
 
         public object Get(GetSocialShareInfo request)
@@ -144,14 +146,14 @@ namespace MediaBrowser.Api.Social
             {
                 if (image.IsLocalFile)
                 {
-                    return ToStaticFileResult(image.Path);
+                    return _resultFactory.GetStaticFileResult(Request, image.Path);
                 }
 
                 try
                 {
                     // Don't fail the request over this
                     var updatedImage = await _libraryManager.ConvertImageToLocal(item, image, 0).ConfigureAwait(false);
-                    return ToStaticFileResult(updatedImage.Path);
+                    return _resultFactory.GetStaticFileResult(Request, updatedImage.Path);
                 }
                 catch
                 {

+ 4 - 2
MediaBrowser.Api/Subtitles/SubtitleService.cs

@@ -135,8 +135,9 @@ namespace MediaBrowser.Api.Subtitles
         private readonly IMediaSourceManager _mediaSourceManager;
         private readonly IProviderManager _providerManager;
         private readonly IFileSystem _fileSystem;
+        private readonly IAuthorizationContext _authContext;
 
-        public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem)
+        public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem, IAuthorizationContext authContext)
         {
             _libraryManager = libraryManager;
             _subtitleManager = subtitleManager;
@@ -144,6 +145,7 @@ namespace MediaBrowser.Api.Subtitles
             _mediaSourceManager = mediaSourceManager;
             _providerManager = providerManager;
             _fileSystem = fileSystem;
+            _authContext = authContext;
         }
 
         public async Task<object> Get(GetSubtitlePlaylist request)
@@ -170,7 +172,7 @@ namespace MediaBrowser.Api.Subtitles
             long positionTicks = 0;
             var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
 
-            var accessToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
+            var accessToken = _authContext.GetAuthorizationInfo(Request).Token;
 
             while (positionTicks < runtime)
             {

+ 4 - 2
MediaBrowser.Api/Sync/SyncService.cs

@@ -161,13 +161,15 @@ namespace MediaBrowser.Api.Sync
         private readonly IDtoService _dtoService;
         private readonly ILibraryManager _libraryManager;
         private readonly IUserManager _userManager;
+        private readonly IAuthorizationContext _authContext;
 
-        public SyncService(ISyncManager syncManager, IDtoService dtoService, ILibraryManager libraryManager, IUserManager userManager)
+        public SyncService(ISyncManager syncManager, IDtoService dtoService, ILibraryManager libraryManager, IUserManager userManager, IAuthorizationContext authContext)
         {
             _syncManager = syncManager;
             _dtoService = dtoService;
             _libraryManager = libraryManager;
             _userManager = userManager;
+            _authContext = authContext;
         }
 
         public object Get(GetSyncTargets request)
@@ -263,7 +265,7 @@ namespace MediaBrowser.Api.Sync
             result.Targets = _syncManager.GetSyncTargets(request.UserId)
                 .ToList();
 
-            var auth = AuthorizationContext.GetAuthorizationInfo(Request);
+            var auth = _authContext.GetAuthorizationInfo(Request);
             var authenticatedUser = _userManager.GetUserById(auth.UserId);
 
             if (!string.IsNullOrWhiteSpace(request.TargetId))

+ 8 - 6
MediaBrowser.Api/TvShowsService.cs

@@ -265,6 +265,7 @@ namespace MediaBrowser.Api
         private readonly IItemRepository _itemRepo;
         private readonly IDtoService _dtoService;
         private readonly ITVSeriesManager _tvSeriesManager;
+        private readonly IAuthorizationContext _authContext;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="TvShowsService" /> class.
@@ -272,7 +273,7 @@ namespace MediaBrowser.Api
         /// <param name="userManager">The user manager.</param>
         /// <param name="userDataManager">The user data repository.</param>
         /// <param name="libraryManager">The library manager.</param>
-        public TvShowsService(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, ITVSeriesManager tvSeriesManager)
+        public TvShowsService(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, ITVSeriesManager tvSeriesManager, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userDataManager = userDataManager;
@@ -280,6 +281,7 @@ namespace MediaBrowser.Api
             _itemRepo = itemRepo;
             _dtoService = dtoService;
             _tvSeriesManager = tvSeriesManager;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -302,7 +304,7 @@ namespace MediaBrowser.Api
                 (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
                 _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
             {
@@ -334,7 +336,7 @@ namespace MediaBrowser.Api
 
             var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
 
-            var options = GetDtoOptions(request);
+            var options = GetDtoOptions(_authContext, request);
 
             var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
             {
@@ -379,7 +381,7 @@ namespace MediaBrowser.Api
 
             var user = _userManager.GetUserById(request.UserId);
 
-            var options = GetDtoOptions(request);
+            var options = GetDtoOptions(_authContext, request);
 
             var returnItems = (await _dtoService.GetBaseItemDtos(result.Items, options, user).ConfigureAwait(false)).ToArray();
 
@@ -434,7 +436,7 @@ namespace MediaBrowser.Api
 
             }).ConfigureAwait(false)).Items.OfType<Season>();
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var returnItems = (await _dtoService.GetBaseItemDtos(seasons, dtoOptions, user).ConfigureAwait(false))
                 .ToArray();
@@ -526,7 +528,7 @@ namespace MediaBrowser.Api
 
             var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = (await _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user).ConfigureAwait(false))
                 .ToArray();

+ 6 - 14
MediaBrowser.Api/UserLibrary/ArtistsService.cs

@@ -49,18 +49,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class ArtistsService : BaseItemsByNameService<MusicArtist>
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ArtistsService" /> class.
-        /// </summary>
-        /// <param name="userManager">The user manager.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        /// <param name="userDataRepository">The user data repository.</param>
-        /// <param name="itemRepo">The item repo.</param>
-        public ArtistsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -81,8 +69,8 @@ namespace MediaBrowser.Api.UserLibrary
         private BaseItemDto GetItem(GetArtist request)
         {
             var item = GetArtist(request.Name, LibraryManager);
-
-            var dtoOptions = GetDtoOptions(request);
+            
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
@@ -148,5 +136,9 @@ namespace MediaBrowser.Api.UserLibrary
         {
             throw new NotImplementedException();
         }
+
+        public ArtistsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 6 - 3
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -7,6 +7,7 @@ using MediaBrowser.Model.Querying;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Services;
 
@@ -30,6 +31,7 @@ namespace MediaBrowser.Api.UserLibrary
         protected readonly IUserDataManager UserDataRepository;
         protected readonly IItemRepository ItemRepository;
         protected IDtoService DtoService { get; private set; }
+        protected IAuthorizationContext AuthorizationContext { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseItemsByNameService{TItemType}" /> class.
@@ -39,13 +41,14 @@ namespace MediaBrowser.Api.UserLibrary
         /// <param name="userDataRepository">The user data repository.</param>
         /// <param name="itemRepository">The item repository.</param>
         /// <param name="dtoService">The dto service.</param>
-        protected BaseItemsByNameService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService)
+        protected BaseItemsByNameService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext)
         {
             UserManager = userManager;
             LibraryManager = libraryManager;
             UserDataRepository = userDataRepository;
             ItemRepository = itemRepository;
             DtoService = dtoService;
+            AuthorizationContext = authorizationContext;
         }
 
         protected BaseItem GetParentItem(GetItemsByName request)
@@ -86,7 +89,7 @@ namespace MediaBrowser.Api.UserLibrary
 
         protected ItemsResult GetResultSlim(GetItemsByName request)
         {
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
             User user = null;
             BaseItem parentItem;
@@ -223,7 +226,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>Task{ItemsResult}.</returns>
         protected ItemsResult GetResult(GetItemsByName request)
         {
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
             User user = null;
             BaseItem parentItem;

+ 6 - 7
MediaBrowser.Api/UserLibrary/GameGenresService.cs

@@ -37,11 +37,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class GameGenresService : BaseItemsByNameService<GameGenre>
     {
-        public GameGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -63,8 +58,8 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var item = GetGameGenre(request.Name, LibraryManager);
 
-            var dtoOptions = GetDtoOptions(request);
-
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
+            
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
                 var user = UserManager.GetUserById(request.UserId);
@@ -102,5 +97,9 @@ namespace MediaBrowser.Api.UserLibrary
         {
             throw new NotImplementedException();
         }
+
+        public GameGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 6 - 7
MediaBrowser.Api/UserLibrary/GenresService.cs

@@ -47,11 +47,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class GenresService : BaseItemsByNameService<Genre>
     {
-        public GenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -72,8 +67,8 @@ namespace MediaBrowser.Api.UserLibrary
         private BaseItemDto GetItem(GetGenre request)
         {
             var item = GetGenre(request.Name, LibraryManager);
-
-            var dtoOptions = GetDtoOptions(request);
+            
+            var dtoOptions = GetDtoOptions(AuthorizationContext ,request);
 
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
@@ -124,5 +119,9 @@ namespace MediaBrowser.Api.UserLibrary
         {
             throw new NotImplementedException();
         }
+
+        public GenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 4 - 2
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -41,6 +41,7 @@ namespace MediaBrowser.Api.UserLibrary
         private readonly ILocalizationManager _localization;
 
         private readonly IDtoService _dtoService;
+        private readonly IAuthorizationContext _authContext;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ItemsService" /> class.
@@ -49,7 +50,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <param name="libraryManager">The library manager.</param>
         /// <param name="localization">The localization.</param>
         /// <param name="dtoService">The dto service.</param>
-        public ItemsService(IUserManager userManager, ILibraryManager libraryManager, ILocalizationManager localization, IDtoService dtoService)
+        public ItemsService(IUserManager userManager, ILibraryManager libraryManager, ILocalizationManager localization, IDtoService dtoService, IAuthorizationContext authContext)
         {
             if (userManager == null)
             {
@@ -72,6 +73,7 @@ namespace MediaBrowser.Api.UserLibrary
             _libraryManager = libraryManager;
             _localization = localization;
             _dtoService = dtoService;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -100,7 +102,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = await GetQueryResult(request, dtoOptions, user).ConfigureAwait(false);
 

+ 6 - 7
MediaBrowser.Api/UserLibrary/MusicGenresService.cs

@@ -38,11 +38,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class MusicGenresService : BaseItemsByNameService<MusicGenre>
     {
-        public MusicGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -63,8 +58,8 @@ namespace MediaBrowser.Api.UserLibrary
         private BaseItemDto GetItem(GetMusicGenre request)
         {
             var item = GetMusicGenre(request.Name, LibraryManager);
-
-            var dtoOptions = GetDtoOptions(request);
+            
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
@@ -103,5 +98,9 @@ namespace MediaBrowser.Api.UserLibrary
         {
             throw new NotImplementedException();
         }
+
+        public MusicGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 6 - 14
MediaBrowser.Api/UserLibrary/PersonsService.cs

@@ -45,18 +45,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class PersonsService : BaseItemsByNameService<Person>
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="PersonsService" /> class.
-        /// </summary>
-        /// <param name="userManager">The user manager.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        /// <param name="userDataRepository">The user data repository.</param>
-        /// <param name="itemRepo">The item repo.</param>
-        public PersonsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -77,8 +65,8 @@ namespace MediaBrowser.Api.UserLibrary
         private BaseItemDto GetItem(GetPerson request)
         {
             var item = GetPerson(request.Name, LibraryManager);
-
-            var dtoOptions = GetDtoOptions(request);
+            
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
@@ -155,5 +143,9 @@ namespace MediaBrowser.Api.UserLibrary
 
             return allPeople.Where(i => allIds.Contains(i.ItemId)).OrderBy(p => p.SortOrder ?? int.MaxValue).ThenBy(p => p.Type);
         }
+
+        public PersonsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 11 - 7
MediaBrowser.Api/UserLibrary/PlaystateService.cs

@@ -234,13 +234,17 @@ namespace MediaBrowser.Api.UserLibrary
         private readonly IUserDataManager _userDataRepository;
         private readonly ILibraryManager _libraryManager;
         private readonly ISessionManager _sessionManager;
+        private readonly ISessionContext _sessionContext;
+        private readonly IAuthorizationContext _authContext;
 
-        public PlaystateService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, ISessionManager sessionManager)
+        public PlaystateService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, ISessionManager sessionManager, ISessionContext sessionContext, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userDataRepository = userDataRepository;
             _libraryManager = libraryManager;
             _sessionManager = sessionManager;
+            _sessionContext = sessionContext;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -265,7 +269,7 @@ namespace MediaBrowser.Api.UserLibrary
                 datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
             }
 
-            var session = await GetSession().ConfigureAwait(false);
+            var session = await GetSession(_sessionContext).ConfigureAwait(false);
 
             var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
 
@@ -303,7 +307,7 @@ namespace MediaBrowser.Api.UserLibrary
 
         public void Post(ReportPlaybackStart request)
         {
-            request.SessionId = GetSession().Result.Id;
+            request.SessionId = GetSession(_sessionContext).Result.Id;
 
             var task = _sessionManager.OnPlaybackStart(request);
 
@@ -335,7 +339,7 @@ namespace MediaBrowser.Api.UserLibrary
 
         public void Post(ReportPlaybackProgress request)
         {
-            request.SessionId = GetSession().Result.Id;
+            request.SessionId = GetSession(_sessionContext).Result.Id;
 
             var task = _sessionManager.OnPlaybackProgress(request);
 
@@ -369,10 +373,10 @@ namespace MediaBrowser.Api.UserLibrary
 
             if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
             {
-                ApiEntryPoint.Instance.KillTranscodingJobs(AuthorizationContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true);
+                ApiEntryPoint.Instance.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true);
             }
 
-            request.SessionId = GetSession().Result.Id;
+            request.SessionId = GetSession(_sessionContext).Result.Id;
 
             var task = _sessionManager.OnPlaybackStopped(request);
 
@@ -394,7 +398,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var session = await GetSession().ConfigureAwait(false);
+            var session = await GetSession(_sessionContext).ConfigureAwait(false);
 
             var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
 

+ 6 - 7
MediaBrowser.Api/UserLibrary/StudiosService.cs

@@ -47,11 +47,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class StudiosService : BaseItemsByNameService<Studio>
     {
-        public StudiosService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -73,8 +68,8 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var item = GetStudio(request.Name, LibraryManager);
 
-            var dtoOptions = GetDtoOptions(request);
-
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
+            
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
                 var user = UserManager.GetUserById(request.UserId);
@@ -117,5 +112,9 @@ namespace MediaBrowser.Api.UserLibrary
                 .DistinctNames()
                 .Select(name => LibraryManager.GetStudio(name));
         }
+
+        public StudiosService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 11 - 9
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -270,8 +270,9 @@ namespace MediaBrowser.Api.UserLibrary
         private readonly IDtoService _dtoService;
         private readonly IUserViewManager _userViewManager;
         private readonly IFileSystem _fileSystem;
+        private readonly IAuthorizationContext _authContext;
 
-        public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, IUserViewManager userViewManager, IFileSystem fileSystem)
+        public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, IUserViewManager userViewManager, IFileSystem fileSystem, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _libraryManager = libraryManager;
@@ -279,6 +280,7 @@ namespace MediaBrowser.Api.UserLibrary
             _dtoService = dtoService;
             _userViewManager = userViewManager;
             _fileSystem = fileSystem;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -315,7 +317,7 @@ namespace MediaBrowser.Api.UserLibrary
                 UserId = request.UserId
             });
 
-            var options = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = list.Select(i =>
             {
@@ -328,7 +330,7 @@ namespace MediaBrowser.Api.UserLibrary
                     childCount = i.Item2.Count;
                 }
 
-                var dto = _dtoService.GetBaseItemDto(item, options, user);
+                var dto = _dtoService.GetBaseItemDto(item, dtoOptions, user);
 
                 dto.ChildCount = childCount;
 
@@ -351,7 +353,7 @@ namespace MediaBrowser.Api.UserLibrary
             // Get them from the child tree
             if (series != null)
             {
-                var dtoOptions = GetDtoOptions(request);
+                var dtoOptions = GetDtoOptions(_authContext, request);
 
                 // Avoid implicitly captured closure
                 var currentUser = user;
@@ -382,7 +384,7 @@ namespace MediaBrowser.Api.UserLibrary
             // Get them from the db
             if (movie != null)
             {
-                var dtoOptions = GetDtoOptions(request);
+                var dtoOptions = GetDtoOptions(_authContext, request);
 
                 var dtos = movie.SpecialFeatureIds
                     .Select(_libraryManager.GetItemById)
@@ -421,7 +423,7 @@ namespace MediaBrowser.Api.UserLibrary
                 trailerIds = hasTrailers.GetTrailerIds();
             }
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = trailerIds
                 .Select(_libraryManager.GetItemById)
@@ -443,7 +445,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
 
@@ -482,7 +484,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var item = user.RootFolder;
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
 
@@ -502,7 +504,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
                 .ToArray();

+ 6 - 3
MediaBrowser.Api/UserLibrary/UserViewsService.cs

@@ -10,6 +10,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Services;
 
 namespace MediaBrowser.Api.UserLibrary
@@ -57,12 +58,14 @@ namespace MediaBrowser.Api.UserLibrary
         private readonly IUserManager _userManager;
         private readonly IUserViewManager _userViewManager;
         private readonly IDtoService _dtoService;
+        private readonly IAuthorizationContext _authContext;
 
-        public UserViewsService(IUserManager userManager, IUserViewManager userViewManager, IDtoService dtoService)
+        public UserViewsService(IUserManager userManager, IUserViewManager userViewManager, IDtoService dtoService, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _userViewManager = userViewManager;
             _dtoService = dtoService;
+            _authContext = authContext;
         }
 
         public async Task<object> Get(GetUserViews request)
@@ -82,7 +85,7 @@ namespace MediaBrowser.Api.UserLibrary
                 query.PresetViews = request.PresetViews.Split(',');
             }
 
-            var app = AuthorizationContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
+            var app = _authContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
             if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
             {
                 query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
@@ -91,7 +94,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
             dtoOptions.Fields = new List<ItemFields>();
             dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
             dtoOptions.Fields.Add(ItemFields.DisplayPreferencesId);

+ 6 - 7
MediaBrowser.Api/UserLibrary/YearsService.cs

@@ -45,11 +45,6 @@ namespace MediaBrowser.Api.UserLibrary
     [Authenticated]
     public class YearsService : BaseItemsByNameService<Year>
     {
-        public YearsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
-            : base(userManager, libraryManager, userDataRepository, itemRepo, dtoService)
-        {
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -70,8 +65,8 @@ namespace MediaBrowser.Api.UserLibrary
         private BaseItemDto GetItem(GetYear request)
         {
             var item = LibraryManager.GetYear(request.Year);
-
-            var dtoOptions = GetDtoOptions(request);
+            
+            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
             if (!string.IsNullOrWhiteSpace(request.UserId))
             {
@@ -111,5 +106,9 @@ namespace MediaBrowser.Api.UserLibrary
                 .Distinct()
                 .Select(year => LibraryManager.GetYear(year));
         }
+
+        public YearsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepository, IDtoService dtoService, IAuthorizationContext authorizationContext) : base(userManager, libraryManager, userDataRepository, itemRepository, dtoService, authorizationContext)
+        {
+        }
     }
 }

+ 12 - 10
MediaBrowser.Api/UserService.cs

@@ -246,7 +246,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class UsersService
     /// </summary>
-    public class UserService : BaseApiService, IHasAuthorization
+    public class UserService : BaseApiService
     {
         /// <summary>
         /// The _user manager
@@ -256,14 +256,16 @@ namespace MediaBrowser.Api
         private readonly IServerConfigurationManager _config;
         private readonly INetworkManager _networkManager;
         private readonly IDeviceManager _deviceManager;
+        private readonly IAuthorizationContext _authContext;
 
-        public UserService(IUserManager userManager, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager, IDeviceManager deviceManager)
+        public UserService(IUserManager userManager, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager, IDeviceManager deviceManager, IAuthorizationContext authContext)
         {
             _userManager = userManager;
             _sessionMananger = sessionMananger;
             _config = config;
             _networkManager = networkManager;
             _deviceManager = deviceManager;
+            _authContext = authContext;
         }
 
         public object Get(GetPublicUsers request)
@@ -316,7 +318,7 @@ namespace MediaBrowser.Api
 
             if (filterByDevice)
             {
-                var deviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+                var deviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
 
                 if (!string.IsNullOrWhiteSpace(deviceId))
                 {
@@ -412,7 +414,7 @@ namespace MediaBrowser.Api
 
         public async Task<object> Post(AuthenticateUserByName request)
         {
-            var auth = AuthorizationContext.GetAuthorizationInfo(Request);
+            var auth = _authContext.GetAuthorizationInfo(Request);
 
             var result = await _sessionMananger.AuthenticateNewSession(new AuthenticationRequest
             {
@@ -442,7 +444,7 @@ namespace MediaBrowser.Api
 
         public async Task PostAsync(UpdateUserPassword request)
         {
-            AssertCanUpdateUser(_userManager, request.Id);
+            AssertCanUpdateUser(_authContext, _userManager, request.Id);
 
             var user = _userManager.GetUserById(request.Id);
 
@@ -466,7 +468,7 @@ namespace MediaBrowser.Api
 
                 await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
 
-                var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
+                var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
 
                 await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
             }
@@ -480,7 +482,7 @@ namespace MediaBrowser.Api
         
         public async Task PostAsync(UpdateUserEasyPassword request)
         {
-            AssertCanUpdateUser(_userManager, request.Id);
+            AssertCanUpdateUser(_authContext, _userManager, request.Id);
             
             var user = _userManager.GetUserById(request.Id);
 
@@ -516,7 +518,7 @@ namespace MediaBrowser.Api
             // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
             var id = GetPathValue(1);
 
-            AssertCanUpdateUser(_userManager, id);
+            AssertCanUpdateUser(_authContext, _userManager, id);
 
             var dtoUser = request;
 
@@ -566,7 +568,7 @@ namespace MediaBrowser.Api
 
         public void Post(UpdateUserConfiguration request)
         {
-            AssertCanUpdateUser(_userManager, request.Id);
+            AssertCanUpdateUser(_authContext, _userManager, request.Id);
 
             var task = _userManager.UpdateConfiguration(request.Id, request);
 
@@ -606,7 +608,7 @@ namespace MediaBrowser.Api
                     throw new ArgumentException("There must be at least one enabled user in the system.");
                 }
 
-                var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
+                var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
                 await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
             }
 

+ 4 - 2
MediaBrowser.Api/VideosService.cs

@@ -56,8 +56,9 @@ namespace MediaBrowser.Api
         private readonly IFileSystem _fileSystem;
         private readonly IItemRepository _itemRepo;
         private readonly IServerConfigurationManager _config;
+        private readonly IAuthorizationContext _authContext;
 
-        public VideosService(ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, IItemRepository itemRepo, IFileSystem fileSystem, IServerConfigurationManager config)
+        public VideosService(ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, IItemRepository itemRepo, IFileSystem fileSystem, IServerConfigurationManager config, IAuthorizationContext authContext)
         {
             _libraryManager = libraryManager;
             _userManager = userManager;
@@ -65,6 +66,7 @@ namespace MediaBrowser.Api
             _itemRepo = itemRepo;
             _fileSystem = fileSystem;
             _config = config;
+            _authContext = authContext;
         }
 
         /// <summary>
@@ -82,7 +84,7 @@ namespace MediaBrowser.Api
                                   : _libraryManager.RootFolder)
                            : _libraryManager.GetItemById(request.Id);
 
-            var dtoOptions = GetDtoOptions(request);
+            var dtoOptions = GetDtoOptions(_authContext, request);
 
             var video = item as Video;
             BaseItemDto[] items;

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

@@ -193,9 +193,7 @@
     <Compile Include="Net\AuthorizationInfo.cs" />
     <Compile Include="Net\IAuthorizationContext.cs" />
     <Compile Include="Net\IAuthService.cs" />
-    <Compile Include="Net\IHasAuthorization.cs" />
     <Compile Include="Net\IHasResultFactory.cs" />
-    <Compile Include="Net\IHasSession.cs" />
     <Compile Include="Net\IHttpResultFactory.cs" />
     <Compile Include="Net\IHttpServer.cs" />
     <Compile Include="Net\IServerManager.cs" />

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

@@ -1,12 +0,0 @@
-
-namespace MediaBrowser.Controller.Net
-{
-    public interface IHasAuthorization
-    {
-        /// <summary>
-        /// Gets or sets the authorization context.
-        /// </summary>
-        /// <value>The authorization context.</value>
-        IAuthorizationContext AuthorizationContext { get; set; }
-    }
-}

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

@@ -1,12 +0,0 @@
-
-namespace MediaBrowser.Controller.Net
-{
-    public interface IHasSession
-    {
-        /// <summary>
-        /// Gets or sets the session context.
-        /// </summary>
-        /// <value>The session context.</value>
-        ISessionContext SessionContext { get; set; }
-    }
-}

+ 5 - 0
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -1218,6 +1218,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
 
         public string EscapeSubtitleFilterPath(string path)
         {
+            // https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping
+            // We need to double escape
+
+            var escapeChars = new[] {':', '\'', ','};
+
             return path.Replace('\\', '/').Replace(":/", "\\:/").Replace("'", "'\\\\\\''");
         }
 

+ 1 - 1
MediaBrowser.Model/Serialization/IXmlSerializer.cs

@@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Serialization
         /// <param name="file">The file.</param>
         /// <returns>System.Object.</returns>
         object DeserializeFromFile(Type type, string file);
-
+        
         /// <summary>
         /// Deserializes from bytes.
         /// </summary>

+ 0 - 44
MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs

@@ -1,44 +0,0 @@
-using MediaBrowser.Common;
-using ServiceStack.Configuration;
-
-namespace MediaBrowser.Server.Implementations.HttpServer
-{
-    /// <summary>
-    /// Class ContainerAdapter
-    /// </summary>
-    class ContainerAdapter : IContainerAdapter
-    {
-        /// <summary>
-        /// The _app host
-        /// </summary>
-        private readonly IApplicationHost _appHost;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ContainerAdapter" /> class.
-        /// </summary>
-        /// <param name="appHost">The app host.</param>
-        public ContainerAdapter(IApplicationHost appHost)
-        {
-            _appHost = appHost;
-        }
-        /// <summary>
-        /// Resolves this instance.
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <returns>``0.</returns>
-        public T Resolve<T>()
-        {
-            return _appHost.Resolve<T>();
-        }
-
-        /// <summary>
-        /// Tries the resolve.
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <returns>``0.</returns>
-        public T TryResolve<T>()
-        {
-            return _appHost.TryResolve<T>();
-        }
-    }
-}

+ 51 - 51
MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -1,13 +1,10 @@
-using Funq;
-using MediaBrowser.Common;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Server.Implementations.HttpServer.SocketSharp;
 using ServiceStack;
 using ServiceStack.Host;
-using ServiceStack.Host.Handlers;
 using ServiceStack.Web;
 using System;
 using System.Collections.Generic;
@@ -17,7 +14,6 @@ using System.Net.Security;
 using System.Net.Sockets;
 using System.Reflection;
 using System.Security.Cryptography.X509Certificates;
-using System.Threading;
 using System.Threading.Tasks;
 using Emby.Common.Implementations.Net;
 using Emby.Server.Implementations.HttpServer;
@@ -29,6 +25,7 @@ using MediaBrowser.Model.Cryptography;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Text;
 using SocketHttpListener.Net;
@@ -47,8 +44,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
 
         private IHttpListener _listener;
 
-        private readonly ContainerAdapter _containerAdapter;
-
         public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
         public event EventHandler<WebSocketConnectingEventArgs> WebSocketConnecting;
 
@@ -64,11 +59,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         private readonly ISocketFactory _socketFactory;
         private readonly ICryptoProvider _cryptoProvider;
 
+        private readonly IJsonSerializer _jsonSerializer;
+        private readonly IXmlSerializer _xmlSerializer;
+
         public HttpListenerHost(IServerApplicationHost applicationHost,
             ILogManager logManager,
             IServerConfigurationManager config,
             string serviceName,
-            string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider)
+            string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer)
             : base(serviceName, new Assembly[] { })
         {
             _appHost = applicationHost;
@@ -78,11 +76,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             _textEncoding = textEncoding;
             _socketFactory = socketFactory;
             _cryptoProvider = cryptoProvider;
+            _jsonSerializer = jsonSerializer;
+            _xmlSerializer = xmlSerializer;
             _config = config;
 
             _logger = logManager.GetLogger("HttpServer");
-
-            _containerAdapter = new ContainerAdapter(applicationHost);
         }
 
         public string GlobalResponse { get; set; }
@@ -106,19 +104,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                 {typeof (NotSupportedException), 500}
             };
 
-            // The Markdown feature causes slow startup times (5 mins+) on cold boots for some users
-            // Custom format allows images
-            HostConfig.Instance.EnableFeatures = Feature.Html | Feature.Json | Feature.Xml | Feature.CustomFormat;
-
-            Container.Adapter = _containerAdapter;
-
             var requestFilters = _appHost.GetExports<IRequestFilter>().ToList();
             foreach (var filter in requestFilters)
             {
-                HostContext.GlobalRequestFilters.Add(filter.Filter);
+                GlobalRequestFilters.Add(filter.Filter);
             }
 
-            HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
+            GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
         }
 
         protected override ILogger Logger
@@ -129,6 +121,21 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             }
         }
 
+        public override T Resolve<T>()
+        {
+            return _appHost.Resolve<T>();
+        }
+
+        public override T TryResolve<T>()
+        {
+            return _appHost.TryResolve<T>();
+        }
+
+        public override object CreateInstance(Type type)
+        {
+            return _appHost.CreateInstance(type);
+        }
+
         public override void OnConfigLoad()
         {
             base.OnConfigLoad();
@@ -241,6 +248,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         {
             try
             {
+                _logger.ErrorException("Error processing request", ex);
+
                 var httpRes = httpReq.Response;
 
                 if (httpRes.IsClosed)
@@ -248,39 +257,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                     return;
                 }
 
-                var errorResponse = new ErrorResponse
-                {
-                    ResponseStatus = new ResponseStatus
-                    {
-                        ErrorCode = ex.GetType().GetOperationName(),
-                        Message = ex.Message,
-                        StackTrace = ex.StackTrace
-                    }
-                };
-
-                var contentType = httpReq.ResponseContentType;
-
-                var serializer = ContentTypes.Instance.GetResponseSerializer(contentType);
-                if (serializer == null)
-                {
-                    contentType = HostContext.Config.DefaultContentType;
-                    serializer = ContentTypes.Instance.GetResponseSerializer(contentType);
-                }
-
-                var httpError = ex as IHttpError;
-                if (httpError != null)
-                {
-                    httpRes.StatusCode = httpError.Status;
-                    httpRes.StatusDescription = httpError.StatusDescription;
-                }
-                else
-                {
-                    httpRes.StatusCode = 500;
-                }
-
-                httpRes.ContentType = contentType;
+                httpRes.StatusCode = 500;
 
-                serializer(httpReq, errorResponse, httpRes);
+                httpRes.ContentType = "text/html";
+                httpRes.Write(ex.Message);
 
                 httpRes.Close();
             }
@@ -571,7 +551,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         public static void RedirectToUrl(IResponse httpRes, string url)
         {
             httpRes.StatusCode = 302;
-            httpRes.AddHeader(HttpHeaders.Location, url);
+            httpRes.AddHeader("Location", url);
         }
 
 
@@ -622,6 +602,26 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             return routes.ToArray();
         }
 
+        public override void SerializeToJson(object o, Stream stream)
+        {
+            _jsonSerializer.SerializeToStream(o, stream);
+        }
+
+        public override void SerializeToXml(object o, Stream stream)
+        {
+            _xmlSerializer.SerializeToStream(o, stream);
+        }
+
+        public override object DeserializeXml(Type type, Stream stream)
+        {
+            return _xmlSerializer.DeserializeFromStream(type, stream);
+        }
+
+        public override object DeserializeJson(Type type, Stream stream)
+        {
+            return _jsonSerializer.DeserializeFromStream(stream, type);
+        }
+
         private string NormalizeEmbyRoutePath(string path)
         {
             if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))

+ 152 - 6
MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -6,13 +6,17 @@ using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
+using System.IO.Compression;
 using System.Net;
+using System.Runtime.Serialization;
 using System.Text;
 using System.Threading.Tasks;
+using System.Xml;
 using Emby.Server.Implementations.HttpServer;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Services;
 using ServiceStack;
+using ServiceStack.Host;
 using IRequest = MediaBrowser.Model.Services.IRequest;
 using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
 using StreamWriter = Emby.Server.Implementations.HttpServer.StreamWriter;
@@ -30,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         private readonly ILogger _logger;
         private readonly IFileSystem _fileSystem;
         private readonly IJsonSerializer _jsonSerializer;
+        private readonly IXmlSerializer _xmlSerializer;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="HttpResultFactory" /> class.
@@ -37,10 +42,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// <param name="logManager">The log manager.</param>
         /// <param name="fileSystem">The file system.</param>
         /// <param name="jsonSerializer">The json serializer.</param>
-        public HttpResultFactory(ILogManager logManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
+        public HttpResultFactory(ILogManager logManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer)
         {
             _fileSystem = fileSystem;
             _jsonSerializer = jsonSerializer;
+            _xmlSerializer = xmlSerializer;
             _logger = logManager.GetLogger("HttpResultFactory");
         }
 
@@ -130,7 +136,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                 throw new ArgumentNullException("result");
             }
 
-            var optimizedResult = requestContext.ToOptimizedResult(result);
+            var optimizedResult = ToOptimizedResult(requestContext, result);
 
             if (responseHeaders == null)
             {
@@ -152,7 +158,99 @@ namespace MediaBrowser.Server.Implementations.HttpServer
 
             return optimizedResult;
         }
-        
+
+        public static string GetCompressionType(IRequest request)
+        {
+            var prefs = new RequestPreferences(request);
+
+            if (prefs.AcceptsDeflate)
+                return "deflate";
+
+            if (prefs.AcceptsGzip)
+                return "gzip";
+
+            return null;
+        }
+
+        /// <summary>
+        /// Returns the optimized result for the IRequestContext. 
+        /// Does not use or store results in any cache.
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public object ToOptimizedResult<T>(IRequest request, T dto)
+        {
+            request.Response.Dto = dto;
+
+            var compressionType = GetCompressionType(request);
+            if (compressionType == null)
+            {
+                var contentType = request.ResponseContentType;
+                var contentTypeAttr = ContentFormat.GetEndpointAttributes(contentType);
+
+                switch (contentTypeAttr)
+                {
+                    case RequestAttributes.Xml:
+                        return SerializeToXmlString(dto);
+
+                    case RequestAttributes.Json:
+                        return _jsonSerializer.SerializeToString(dto);
+                }
+            }
+
+            using (var ms = new MemoryStream())
+            {
+                using (var compressionStream = GetCompressionStream(ms, compressionType))
+                {
+                    ContentTypes.Instance.SerializeToStream(request, dto, compressionStream);
+                    compressionStream.Close();
+
+                    var compressedBytes = ms.ToArray();
+
+                    var httpResult = new HttpResult(compressedBytes, request.ResponseContentType)
+                    {
+                        Status = request.Response.StatusCode
+                    };
+
+                    httpResult.Headers["Content-Length"] = compressedBytes.Length.ToString(UsCulture);
+                    httpResult.Headers["Content-Encoding"] = compressionType;
+
+                    return httpResult;
+                }
+            }
+        }
+
+        public static string SerializeToXmlString(object from)
+        {
+            using (var ms = new MemoryStream())
+            {
+                var xwSettings = new XmlWriterSettings();
+                xwSettings.Encoding = new UTF8Encoding(false);
+                xwSettings.OmitXmlDeclaration = false;
+
+                using (var xw = XmlWriter.Create(ms, xwSettings))
+                {
+                    var serializer = new DataContractSerializer(from.GetType());
+                    serializer.WriteObject(xw, from);
+                    xw.Flush();
+                    ms.Seek(0, SeekOrigin.Begin);
+                    var reader = new StreamReader(ms);
+                    return reader.ReadToEnd();
+                }
+            }
+        }
+
+        private static Stream GetCompressionStream(Stream outputStream, string compressionType)
+        {
+            if (compressionType == "deflate")
+                return new DeflateStream(outputStream, CompressionMode.Compress);
+            if (compressionType == "gzip")
+                return new GZipStream(outputStream, CompressionMode.Compress);
+
+            throw new NotSupportedException(compressionType);
+        }
+
         /// <summary>
         /// Gets the optimized result using cache.
         /// </summary>
@@ -471,7 +569,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             var contentType = options.ContentType;
             var responseHeaders = options.ResponseHeaders;
 
-            var requestedCompressionType = requestContext.GetCompressionType();
+            var requestedCompressionType = GetCompressionType(requestContext);
 
             if (!compress || string.IsNullOrEmpty(requestedCompressionType))
             {
@@ -513,16 +611,64 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                 }
             }
 
-            var contents = content.Compress(requestedCompressionType);
+            var contents = Compress(content, requestedCompressionType);
 
             responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture);
+            responseHeaders["Content-Encoding"] = requestedCompressionType;
 
             if (isHeadRequest)
             {
                 return GetHttpResult(new byte[] { }, contentType);
             }
 
-            return new CompressedResult(contents, requestedCompressionType, contentType);
+            return GetHttpResult(contents, contentType, responseHeaders);
+        }
+
+        public static byte[] Compress(string text, string compressionType)
+        {
+            if (compressionType == "deflate")
+                return Deflate(text);
+
+            if (compressionType == "gzip")
+                return GZip(text);
+
+            throw new NotSupportedException(compressionType);
+        }
+
+        public static byte[] Deflate(string text)
+        {
+            return Deflate(Encoding.UTF8.GetBytes(text));
+        }
+
+        public static byte[] Deflate(byte[] bytes)
+        {
+            // In .NET FX incompat-ville, you can't access compressed bytes without closing DeflateStream
+            // Which means we must use MemoryStream since you have to use ToArray() on a closed Stream
+            using (var ms = new MemoryStream())
+            using (var zipStream = new DeflateStream(ms, CompressionMode.Compress))
+            {
+                zipStream.Write(bytes, 0, bytes.Length);
+                zipStream.Close();
+
+                return ms.ToArray();
+            }
+        }
+
+        public static byte[] GZip(string text)
+        {
+            return GZip(Encoding.UTF8.GetBytes(text));
+        }
+
+        public static byte[] GZip(byte[] buffer)
+        {
+            using (var ms = new MemoryStream())
+            using (var zipStream = new GZipStream(ms, CompressionMode.Compress))
+            {
+                zipStream.Write(buffer, 0, buffer.Length);
+                zipStream.Close();
+
+                return ms.ToArray();
+            }
         }
 
         /// <summary>

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

@@ -6,6 +6,7 @@ using MediaBrowser.Model.Cryptography;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Text;
 
 namespace MediaBrowser.Server.Implementations.HttpServer
@@ -28,9 +29,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             string defaultRedirectpath,
             ITextEncoding textEncoding,
             ISocketFactory socketFactory,
-            ICryptoProvider cryptoProvider)
+            ICryptoProvider cryptoProvider,
+            IJsonSerializer json,
+            IXmlSerializer xml)
         {
-            return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider, textEncoding, socketFactory, cryptoProvider);
+            return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider, textEncoding, socketFactory, cryptoProvider, json, xml);
         }
     }
 }

+ 24 - 8
MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs

@@ -3,7 +3,6 @@ using System.Collections.Generic;
 using System.IO;
 using System.Text;
 using Emby.Server.Implementations.HttpServer.SocketSharp;
-using Funq;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Services;
@@ -19,7 +18,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
 {
     public partial class WebSocketSharpRequest : IHttpRequest
     {
-        public Container Container { get; set; }
         private readonly HttpListenerRequest request;
         private readonly IHttpResponse response;
         private readonly IMemoryStreamFactory _memoryStreamProvider;
@@ -239,6 +237,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
             }
         }
 
+        public const string FormUrlEncoded = "application/x-www-form-urlencoded";
+        public const string MultiPartFormData = "multipart/form-data";
         private static string GetResponseContentType(IRequest httpReq)
         {
             var specifiedContentType = GetQueryStringContentType(httpReq);
@@ -246,7 +246,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
 
             var acceptContentTypes = httpReq.AcceptTypes;
             var defaultContentType = httpReq.ContentType;
-            if (httpReq.HasAnyOfContentTypes(MimeTypes.FormUrlEncoded, MimeTypes.MultiPartFormData))
+            if (HasAnyOfContentTypes(httpReq, FormUrlEncoded, MultiPartFormData))
             {
                 defaultContentType = HostContext.Config.DefaultContentType;
             }
@@ -299,15 +299,32 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
                 }
             }
 
-            if (acceptContentTypes == null && httpReq.ContentType == MimeTypes.Soap11)
+            if (acceptContentTypes == null && httpReq.ContentType == Soap11)
             {
-                return MimeTypes.Soap11;
+                return Soap11;
             }
 
             //We could also send a '406 Not Acceptable', but this is allowed also
             return HostContext.Config.DefaultContentType;
         }
+        public const string Soap11 = "text/xml; charset=utf-8";
 
+        public static bool HasAnyOfContentTypes(IRequest request, params string[] contentTypes)
+        {
+            if (contentTypes == null || request.ContentType == null) return false;
+            foreach (var contentType in contentTypes)
+            {
+                if (IsContentType(request, contentType)) return true;
+            }
+            return false;
+        }
+
+        public static bool IsContentType(IRequest request, string contentType)
+        {
+            return request.ContentType.StartsWith(contentType, StringComparison.OrdinalIgnoreCase);
+        }
+
+        public const string Xml = "application/xml";
         private static string GetQueryStringContentType(IRequest httpReq)
         {
             var format = httpReq.QueryString["format"];
@@ -323,7 +340,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
 
             format = format.LeftPart('.').ToLower();
             if (format.Contains("json")) return "application/json";
-            if (format.Contains("xml")) return MimeTypes.Xml;
+            if (format.Contains("xml")) return Xml;
 
             string contentType;
             ContentTypes.Instance.ContentTypeFormats.TryGetValue(format, out contentType);
@@ -464,8 +481,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
             get
             {
                 return httpMethod
-                    ?? (httpMethod = Param(HttpHeaders.XHttpMethodOverride)
-                    ?? request.HttpMethod);
+                    ?? (httpMethod = request.HttpMethod);
             }
         }
 

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

@@ -88,9 +88,6 @@
     <Reference Include="ServiceStack">
       <HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
     </Reference>
-    <Reference Include="ServiceStack.Interfaces">
-      <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
-    </Reference>
     <Reference Include="ServiceStack.Text">
       <HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
     </Reference>
@@ -111,7 +108,6 @@
     <Compile Include="Devices\DeviceRepository.cs" />
     <Compile Include="Devices\CameraUploadsFolder.cs" />
     <Compile Include="EntryPoints\ExternalPortForwarding.cs" />
-    <Compile Include="HttpServer\ContainerAdapter.cs" />
     <Compile Include="HttpServer\HttpListenerHost.cs" />
     <Compile Include="HttpServer\HttpResultFactory.cs" />
     <Compile Include="HttpServer\ServerFactory.cs" />

+ 1 - 20
MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj

@@ -98,30 +98,11 @@
     <Compile Include="..\SharedVersion.cs">
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
-    <Compile Include="Native\BaseMonoApp.cs" />
+    <Compile Include="Native\MonoApp.cs" />
     <Compile Include="Native\DbConnector.cs" />
     <Compile Include="Native\PowerManagement.cs" />
-    <Compile Include="Networking\CertificateGenerator.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Native\NativeApp.cs" />
-    <Compile Include="Networking\NetworkManager.cs" />
-    <Compile Include="Security\ASN1.cs" />
-    <Compile Include="Security\ASN1Convert.cs" />
-    <Compile Include="Security\BitConverterLE.cs" />
-    <Compile Include="Security\CryptoConvert.cs" />
-    <Compile Include="Security\PKCS1.cs" />
-    <Compile Include="Security\PKCS12.cs" />
-    <Compile Include="Security\PKCS7.cs" />
-    <Compile Include="Security\PKCS8.cs" />
-    <Compile Include="Security\X501Name.cs" />
-    <Compile Include="Security\X509Builder.cs" />
-    <Compile Include="Security\X509Certificate.cs" />
-    <Compile Include="Security\X509CertificateBuilder.cs" />
-    <Compile Include="Security\X509CertificateCollection.cs" />
-    <Compile Include="Security\X509Extension.cs" />
-    <Compile Include="Security\X509Extensions.cs" />
-    <Compile Include="Security\X520Attributes.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>

+ 17 - 13
MediaBrowser.Server.Mono/Native/BaseMonoApp.cs → MediaBrowser.Server.Mono/Native/MonoApp.cs

@@ -1,7 +1,6 @@
 using MediaBrowser.Common.Net;
 using MediaBrowser.IsoMounter;
 using MediaBrowser.Model.Logging;
-using MediaBrowser.Server.Mono.Networking;
 using MediaBrowser.Server.Startup.Common;
 using Mono.Unix.Native;
 using System;
@@ -11,16 +10,17 @@ using System.Text.RegularExpressions;
 using MediaBrowser.Model.System;
 using MediaBrowser.Server.Implementations.Persistence;
 using MediaBrowser.Server.Startup.Common.FFMpeg;
+using MediaBrowser.Server.Startup.Common.Networking;
 using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem;
 
 namespace MediaBrowser.Server.Mono.Native
 {
-    public abstract class BaseMonoApp : INativeApp
+    public class MonoApp : INativeApp
     {
         protected StartupOptions StartupOptions { get; private set; }
         protected ILogger Logger { get; private set; }
 
-        protected BaseMonoApp(StartupOptions startupOptions, ILogger logger)
+        public MonoApp(StartupOptions startupOptions, ILogger logger)
         {
             StartupOptions = startupOptions;
             Logger = logger;
@@ -29,28 +29,32 @@ namespace MediaBrowser.Server.Mono.Native
         /// <summary>
         /// Shutdowns this instance.
         /// </summary>
-        public abstract void Shutdown();
-
-        /// <summary>
-        /// Restarts this instance.
-        /// </summary>
-        public virtual void Restart(StartupOptions startupOptions)
+        public void Shutdown()
         {
-            throw new NotImplementedException();
+            MainClass.Shutdown();
         }
 
         /// <summary>
         /// Determines whether this instance [can self restart].
         /// </summary>
-        /// <returns><c>true</c> if this instance [can self restart]; otherwise, <c>false</c>.</returns>
-        public virtual bool CanSelfRestart
+        /// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
+        public bool CanSelfRestart
         {
             get
             {
-                return false;
+                // A restart script must be provided
+                return StartupOptions.ContainsOption("-restartpath");
             }
         }
 
+        /// <summary>
+        /// Restarts this instance.
+        /// </summary>
+        public void Restart(StartupOptions startupOptions)
+        {
+            MainClass.Restart(startupOptions);
+        }
+
         /// <summary>
         /// Gets a value indicating whether this instance can self update.
         /// </summary>

+ 0 - 45
MediaBrowser.Server.Mono/Native/NativeApp.cs

@@ -1,45 +0,0 @@
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Server.Startup.Common;
-
-namespace MediaBrowser.Server.Mono.Native
-{
-    /// <summary>
-    /// Class NativeApp
-    /// </summary>
-    internal class NativeApp : BaseMonoApp
-    {
-        public NativeApp(StartupOptions startupOptions, ILogger logger)
-            : base(startupOptions, logger)
-        {
-        }
-
-        /// <summary>
-        /// Shutdowns this instance.
-        /// </summary>
-        public override void Shutdown()
-        {
-            MainClass.Shutdown();
-        }
-
-        /// <summary>
-        /// Determines whether this instance [can self restart].
-        /// </summary>
-        /// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
-        public override bool CanSelfRestart
-        {
-            get
-            {
-                // A restart script must be provided
-                return StartupOptions.ContainsOption("-restartpath");
-            }
-        }
-
-        /// <summary>
-        /// Restarts this instance.
-        /// </summary>
-        public override void Restart(StartupOptions startupOptions)
-        {
-            MainClass.Restart(startupOptions);
-        }
-    }
-}

+ 1 - 1
MediaBrowser.Server.Mono/Program.cs

@@ -78,7 +78,7 @@ namespace MediaBrowser.Server.Mono
             var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), false, false);
             fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
 
-            var nativeApp = new NativeApp(options, logManager.GetLogger("App"));
+            var nativeApp = new MonoApp(options, logManager.GetLogger("App"));
 
             _appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, nativeApp, new PowerManagement(), "emby.mono.zip");
 

+ 2 - 2
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -552,7 +552,7 @@ namespace MediaBrowser.Server.Startup.Common
             ZipClient = new ZipClient(FileSystemManager);
             RegisterSingleInstance(ZipClient);
 
-            RegisterSingleInstance<IHttpResultFactory>(new HttpResultFactory(LogManager, FileSystemManager, JsonSerializer));
+            RegisterSingleInstance<IHttpResultFactory>(new HttpResultFactory(LogManager, FileSystemManager, JsonSerializer, XmlSerializer));
 
             RegisterSingleInstance<IServerApplicationHost>(this);
             RegisterSingleInstance<IServerApplicationPaths>(ApplicationPaths);
@@ -612,7 +612,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);
+            HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer);
             HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
             RegisterSingleInstance(HttpServer, false);
             progress.Report(10);

+ 20 - 4
MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj

@@ -22,6 +22,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>None</DebugType>
@@ -47,10 +48,6 @@
       <HintPath>..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll</HintPath>
       <Private>True</Private>
     </Reference>
-    <Reference Include="ServiceStack.Interfaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=e06fbc6124f57c43, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
-    </Reference>
     <Reference Include="ServiceStack.Text, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
@@ -85,7 +82,26 @@
     <Compile Include="Migrations\DbMigration.cs" />
     <Compile Include="Migrations\UpdateLevelMigration.cs" />
     <Compile Include="NativeEnvironment.cs" />
+    <Compile Include="Security\CertificateGenerator.cs" />
+    <Compile Include="Networking\NetworkManager.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Security\ASN1.cs" />
+    <Compile Include="Security\ASN1Convert.cs" />
+    <Compile Include="Security\BitConverterLE.cs" />
+    <Compile Include="Security\CryptoConvert.cs" />
+    <Compile Include="Security\PfxGenerator.cs" />
+    <Compile Include="Security\PKCS1.cs" />
+    <Compile Include="Security\PKCS12.cs" />
+    <Compile Include="Security\PKCS7.cs" />
+    <Compile Include="Security\PKCS8.cs" />
+    <Compile Include="Security\X501Name.cs" />
+    <Compile Include="Security\X509Builder.cs" />
+    <Compile Include="Security\X509Certificate.cs" />
+    <Compile Include="Security\X509CertificateBuilder.cs" />
+    <Compile Include="Security\X509CertificateCollection.cs" />
+    <Compile Include="Security\X509Extension.cs" />
+    <Compile Include="Security\X509Extensions.cs" />
+    <Compile Include="Security\X520Attributes.cs" />
     <Compile Include="StartupOptions.cs" />
     <Compile Include="SystemEvents.cs" />
     <Compile Include="TextLocalizer.cs" />

+ 5 - 4
MediaBrowser.Server.Mono/Networking/NetworkManager.cs → MediaBrowser.Server.Startup.Common/Networking/NetworkManager.cs

@@ -1,11 +1,12 @@
-using MediaBrowser.Common.Net;
+using System.Collections.Generic;
+using Emby.Common.Implementations.Networking;
+using Emby.Common.Implementations.Security;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
-using System.Collections.Generic;
-using Emby.Common.Implementations.Networking;
 
-namespace MediaBrowser.Server.Mono.Networking
+namespace MediaBrowser.Server.Startup.Common.Networking
 {
     /// <summary>
     /// Class NetUtils

+ 1 - 1
MediaBrowser.Server.Mono/Security/ASN1.cs → MediaBrowser.Server.Startup.Common/Security/ASN1.cs

@@ -34,7 +34,7 @@ using System.Collections;
 using System.IO;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security {
 
 	// References:
 	// a.	ITU ASN.1 standards (free download)

+ 5 - 4
MediaBrowser.Server.Mono/Security/ASN1Convert.cs → MediaBrowser.Server.Startup.Common/Security/ASN1Convert.cs

@@ -34,11 +34,12 @@ using System.Globalization;
 using System.Security.Cryptography;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
-	// References:
-	// a.	ITU ASN.1 standards (free download)
-	//	http://www.itu.int/ITU-T/studygroups/com17/languages/
+    // References:
+    // a.	ITU ASN.1 standards (free download)
+    //	http://www.itu.int/ITU-T/studygroups/com17/languages/
 
     public static class ASN1Convert {
 		// RFC3280, section 4.2.1.5

+ 2 - 2
MediaBrowser.Server.Mono/Security/BitConverterLE.cs → MediaBrowser.Server.Startup.Common/Security/BitConverterLE.cs

@@ -29,9 +29,9 @@
 
 using System;
 
-namespace MediaBrowser.Server.Mono.Security
+namespace Emby.Common.Implementations.Security
 {
-	internal sealed class BitConverterLE
+    internal sealed class BitConverterLE
 	{
 		private BitConverterLE ()
 		{

+ 1 - 2
MediaBrowser.Server.Mono/Networking/CertificateGenerator.cs → MediaBrowser.Server.Startup.Common/Security/CertificateGenerator.cs

@@ -2,9 +2,8 @@
 using System;
 using System.Collections;
 using System.Security.Cryptography;
-using MediaBrowser.Server.Mono.Security;
 
-namespace MediaBrowser.Server.Mono.Networking
+namespace Emby.Common.Implementations.Security
 {
     internal class CertificateGenerator
     {

+ 2 - 1
MediaBrowser.Server.Mono/Security/CryptoConvert.cs → MediaBrowser.Server.Startup.Common/Security/CryptoConvert.cs

@@ -32,7 +32,8 @@ using System.Globalization;
 using System.Security.Cryptography;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
     public sealed class CryptoConvert {
 

+ 6 - 5
MediaBrowser.Server.Mono/Security/PKCS1.cs → MediaBrowser.Server.Startup.Common/Security/PKCS1.cs

@@ -31,12 +31,13 @@
 using System;
 using System.Security.Cryptography;
 
-namespace MediaBrowser.Server.Mono.Security { 
+namespace Emby.Common.Implementations.Security
+{
+
+    // References:
+    // a.	PKCS#1: RSA Cryptography Standard 
+    //	http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/index.html
 
-	// References:
-	// a.	PKCS#1: RSA Cryptography Standard 
-	//	http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/index.html
-	
     public sealed class PKCS1 {
 
 		private PKCS1 () 

+ 2 - 1
MediaBrowser.Server.Mono/Security/PKCS12.cs → MediaBrowser.Server.Startup.Common/Security/PKCS12.cs

@@ -37,7 +37,8 @@ using System.IO;
 using System.Security.Cryptography;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
     public class PKCS5 {
 

+ 2 - 1
MediaBrowser.Server.Mono/Security/PKCS7.cs → MediaBrowser.Server.Startup.Common/Security/PKCS7.cs

@@ -33,7 +33,8 @@ using System;
 using System.Collections;
 using System.Security.Cryptography;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
     public sealed class PKCS7 {
 

+ 2 - 1
MediaBrowser.Server.Mono/Security/PKCS8.cs → MediaBrowser.Server.Startup.Common/Security/PKCS8.cs

@@ -33,7 +33,8 @@ using System;
 using System.Collections;
 using System.Security.Cryptography;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
     public sealed class PKCS8 {
 

+ 75 - 0
MediaBrowser.Server.Startup.Common/Security/PfxGenerator.cs

@@ -0,0 +1,75 @@
+using System;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace Emby.Common.Implementations.Security
+{
+    public class PFXGenerator
+    {
+        // http://www.freekpaans.nl/2015/04/creating-self-signed-x-509-certificates-using-mono-security/
+        public static byte[] GeneratePfx(string certificateName, string password)
+        {
+            byte[] sn = GenerateSerialNumber();
+            string subject = string.Format("CN={0}", certificateName);
+
+            DateTime notBefore = DateTime.Now;
+            DateTime notAfter = DateTime.Now.AddYears(20);
+
+            RSA subjectKey = new RSACryptoServiceProvider(2048);
+
+
+            string hashName = "SHA256";
+
+            X509CertificateBuilder cb = new X509CertificateBuilder(3);
+            cb.SerialNumber = sn;
+            cb.IssuerName = subject;
+            cb.NotBefore = notBefore;
+            cb.NotAfter = notAfter;
+            cb.SubjectName = subject;
+            cb.SubjectPublicKey = subjectKey;
+            cb.Hash = hashName;
+
+            byte[] rawcert = cb.Sign(subjectKey);
+
+
+            PKCS12 p12 = new PKCS12();
+            p12.Password = password;
+
+            Hashtable attributes = GetAttributes();
+
+            p12.AddCertificate(new X509Certificate(rawcert), attributes);
+            p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes);
+
+            return p12.GetBytes();
+        }
+
+        private static Hashtable GetAttributes()
+        {
+            ArrayList list = new ArrayList();
+            // we use a fixed array to avoid endianess issues 
+            // (in case some tools requires the ID to be 1).
+            list.Add(new byte[4] { 1, 0, 0, 0 });
+            Hashtable attributes = new Hashtable(1);
+            attributes.Add(PKCS9.localKeyId, list);
+            return attributes;
+        }
+
+        private static byte[] GenerateSerialNumber()
+        {
+            byte[] sn = Guid.NewGuid().ToByteArray();
+
+            //must be positive
+            if ((sn[0] & 0x80) == 0x80)
+                sn[0] -= 0x80;
+            return sn;
+        }
+
+        public static byte[] GetCertificateForBytes(byte[] pfx, string password)
+        {
+            var pkcs = new PKCS12(pfx, password);
+            var cert = pkcs.GetCertificate(GetAttributes());
+
+            return cert.RawData;
+        }
+    }
+}

+ 8 - 7
MediaBrowser.Server.Mono/Security/X501Name.cs → MediaBrowser.Server.Startup.Common/Security/X501Name.cs

@@ -31,15 +31,16 @@ using System;
 using System.Globalization;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
-	// References:
-	// 1.	Information technology - Open Systems Interconnection - The Directory: Models
-	//	http://www.itu.int/rec/recommendation.asp?type=items&lang=e&parent=T-REC-X.501-200102-I
-	// 2.	RFC2253: Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
-	//	http://www.ietf.org/rfc/rfc2253.txt
+    // References:
+    // 1.	Information technology - Open Systems Interconnection - The Directory: Models
+    //	http://www.itu.int/rec/recommendation.asp?type=items&lang=e&parent=T-REC-X.501-200102-I
+    // 2.	RFC2253: Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
+    //	http://www.ietf.org/rfc/rfc2253.txt
 
-	/*
+    /*
 	 * Name ::= CHOICE { RDNSequence }
 	 * 
 	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

+ 3 - 2
MediaBrowser.Server.Mono/Security/X509Builder.cs → MediaBrowser.Server.Startup.Common/Security/X509Builder.cs

@@ -33,9 +33,10 @@ using System;
 using System.Globalization;
 using System.Security.Cryptography;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
-	public abstract class X509Builder {
+    public abstract class X509Builder {
 
 		private const string defaultHash = "SHA1";
 		private string hashName;

+ 2 - 1
MediaBrowser.Server.Mono/Security/X509Certificate.cs → MediaBrowser.Server.Startup.Common/Security/X509Certificate.cs

@@ -34,7 +34,8 @@ using System.Security.Cryptography;
 using System.Security.Permissions;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
     // References:
     // a.	Internet X.509 Public Key Infrastructure Certificate and CRL Profile

+ 5 - 4
MediaBrowser.Server.Mono/Security/X509CertificateBuilder.cs → MediaBrowser.Server.Startup.Common/Security/X509CertificateBuilder.cs

@@ -32,9 +32,10 @@
 using System;
 using System.Security.Cryptography;
 
-namespace MediaBrowser.Server.Mono.Security {
-	// From RFC3280
-	/*
+namespace Emby.Common.Implementations.Security
+{
+    // From RFC3280
+    /*
 	 * Certificate  ::=  SEQUENCE  {
 	 *      tbsCertificate       TBSCertificate,
 	 *      signatureAlgorithm   AlgorithmIdentifier,
@@ -66,7 +67,7 @@ namespace MediaBrowser.Server.Mono.Security {
 	 *      generalTime    GeneralizedTime 
 	 * }
 	 */
-	public class X509CertificateBuilder : X509Builder {
+    public class X509CertificateBuilder : X509Builder {
  
 		private byte version;
 		private byte[] sn;

+ 3 - 2
MediaBrowser.Server.Mono/Security/X509CertificateCollection.cs → MediaBrowser.Server.Startup.Common/Security/X509CertificateCollection.cs

@@ -31,9 +31,10 @@
 using System;
 using System.Collections;
 
-namespace MediaBrowser.Server.Mono.Security {
+namespace Emby.Common.Implementations.Security
+{
 
-	[Serializable]
+    [Serializable]
     public class X509CertificateCollection : CollectionBase, IEnumerable {
 		
 		public X509CertificateCollection () 

+ 3 - 2
MediaBrowser.Server.Mono/Security/X509Extension.cs → MediaBrowser.Server.Startup.Common/Security/X509Extension.cs

@@ -31,8 +31,9 @@ using System;
 using System.Globalization;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
-	/*
+namespace Emby.Common.Implementations.Security
+{
+    /*
 	 * Extension  ::=  SEQUENCE  {
 	 *	extnID      OBJECT IDENTIFIER,
 	 *	critical    BOOLEAN DEFAULT FALSE,

+ 3 - 2
MediaBrowser.Server.Mono/Security/X509Extensions.cs → MediaBrowser.Server.Startup.Common/Security/X509Extensions.cs

@@ -32,8 +32,9 @@
 using System;
 using System.Collections;
 
-namespace MediaBrowser.Server.Mono.Security {
-	/*
+namespace Emby.Common.Implementations.Security
+{
+    /*
 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
 	 * 
 	 * Note: 1..MAX -> There shouldn't be 0 Extensions in the ASN1 structure

+ 14 - 13
MediaBrowser.Server.Mono/Security/X520Attributes.cs → MediaBrowser.Server.Startup.Common/Security/X520Attributes.cs

@@ -30,19 +30,20 @@
 using System;
 using System.Text;
 
-namespace MediaBrowser.Server.Mono.Security {
-
-	// References:
-	// 1.	Information technology - Open Systems Interconnection - The Directory: Selected attribute types 
-	//	http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-X.520 
-	// 2.	Internet X.509 Public Key Infrastructure Certificate and CRL Profile
-	//	http://www.ietf.org/rfc/rfc3280.txt
-	// 3.	A Summary of the X.500(96) User Schema for use with LDAPv3
-	//	http://www.faqs.org/rfcs/rfc2256.html
-	// 4.	RFC 2247 - Using Domains in LDAP/X.500 Distinguished Names
-	//	http://www.faqs.org/rfcs/rfc2247.html
-
-	/* 
+namespace Emby.Common.Implementations.Security
+{
+
+    // References:
+    // 1.	Information technology - Open Systems Interconnection - The Directory: Selected attribute types 
+    //	http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-X.520 
+    // 2.	Internet X.509 Public Key Infrastructure Certificate and CRL Profile
+    //	http://www.ietf.org/rfc/rfc3280.txt
+    // 3.	A Summary of the X.500(96) User Schema for use with LDAPv3
+    //	http://www.faqs.org/rfcs/rfc2256.html
+    // 4.	RFC 2247 - Using Domains in LDAP/X.500 Distinguished Names
+    //	http://www.faqs.org/rfcs/rfc2247.html
+
+    /* 
 	 * AttributeTypeAndValue ::= SEQUENCE {
 	 * 	type     AttributeType,
 	 * 	value    AttributeValue 

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

@@ -131,7 +131,6 @@
     <Compile Include="Native\Standby.cs" />
     <Compile Include="Native\ServerAuthorization.cs" />
     <Compile Include="Native\WindowsApp.cs" />
-    <Compile Include="Networking\CertificateGenerator.cs" />
     <Compile Include="Networking\NativeMethods.cs" />
     <Compile Include="Networking\NetworkManager.cs" />
     <Compile Include="Networking\NetworkShares.cs" />

+ 0 - 244
MediaBrowser.ServerApplication/Networking/CertificateGenerator.cs

@@ -1,244 +0,0 @@
-using MediaBrowser.Model.Logging;
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace MediaBrowser.ServerApplication.Networking
-{
-        // Copied from: http://blogs.msdn.com/b/dcook/archive/2014/05/16/9143036.aspx
-    // In case anybody is interested, source code is attached and is free for use by anybody as long as you don't hold me or Microsoft liable for it -- 
-    // I have no idea whether this is actually the right or best way to do this. Give it the X500 distinguished name, validity start and end dates, 
-    // and an optional password for encrypting the key data, and it will give you the PFX file data. Let me know if you find any bugs or have any suggestions.
-    internal class CertificateGenerator
-    {
-        internal static void CreateSelfSignCertificatePfx(
-            string fileName,
-            string hostname,
-            ILogger logger)
-        {
-            if (string.IsNullOrWhiteSpace(fileName))
-            {
-                throw new ArgumentNullException("fileName");
-            }
-
-            string x500 = string.Format("CN={0}", hostname);
-
-            DateTime startTime = DateTime.Now.AddDays(-2);
-            DateTime endTime = DateTime.Now.AddYears(10);
-
-            byte[] pfxData = CreateSelfSignCertificatePfx(
-                x500,
-                startTime,
-                endTime);
-
-            File.WriteAllBytes(fileName, pfxData);
-        }
-
-        private static byte[] CreateSelfSignCertificatePfx(
-            string x500,
-            DateTime startTime,
-            DateTime endTime)
-        {
-            byte[] pfxData;
-
-            if (x500 == null)
-            {
-                x500 = "";
-            }
-
-            SystemTime startSystemTime = ToSystemTime(startTime);
-            SystemTime endSystemTime = ToSystemTime(endTime);
-            string containerName = Guid.NewGuid().ToString();
-
-            GCHandle dataHandle = new GCHandle();
-            IntPtr providerContext = IntPtr.Zero;
-            IntPtr cryptKey = IntPtr.Zero;
-            IntPtr certContext = IntPtr.Zero;
-            IntPtr certStore = IntPtr.Zero;
-            IntPtr storeCertContext = IntPtr.Zero;
-            IntPtr passwordPtr = IntPtr.Zero;
-            RuntimeHelpers.PrepareConstrainedRegions();
-            try
-            {
-                Check(NativeMethods.CryptAcquireContextW(
-                    out providerContext,
-                    containerName,
-                    null,
-                    1, // PROV_RSA_FULL
-                    8)); // CRYPT_NEWKEYSET
-
-                Check(NativeMethods.CryptGenKey(
-                    providerContext,
-                    1, // AT_KEYEXCHANGE
-                    1 | 2048 << 16, // CRYPT_EXPORTABLE 2048 bit key
-                    out cryptKey));
-
-                IntPtr errorStringPtr;
-                int nameDataLength = 0;
-                byte[] nameData;
-
-                // errorStringPtr gets a pointer into the middle of the x500 string,
-                // so x500 needs to be pinned until after we've copied the value
-                // of errorStringPtr.
-                dataHandle = GCHandle.Alloc(x500, GCHandleType.Pinned);
-
-                if (!NativeMethods.CertStrToNameW(
-                    0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
-                    dataHandle.AddrOfPinnedObject(),
-                    3, // CERT_X500_NAME_STR = 3
-                    IntPtr.Zero,
-                    null,
-                    ref nameDataLength,
-                    out errorStringPtr))
-                {
-                    string error = Marshal.PtrToStringUni(errorStringPtr);
-                    throw new ArgumentException(error);
-                }
-
-                nameData = new byte[nameDataLength];
-
-                if (!NativeMethods.CertStrToNameW(
-                    0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
-                    dataHandle.AddrOfPinnedObject(),
-                    3, // CERT_X500_NAME_STR = 3
-                    IntPtr.Zero,
-                    nameData,
-                    ref nameDataLength,
-                    out errorStringPtr))
-                {
-                    string error = Marshal.PtrToStringUni(errorStringPtr);
-                    throw new ArgumentException(error);
-                }
-
-                dataHandle.Free();
-
-                dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned);
-                CryptoApiBlob nameBlob = new CryptoApiBlob(
-                    nameData.Length,
-                    dataHandle.AddrOfPinnedObject());
-
-                CryptKeyProviderInformation kpi = new CryptKeyProviderInformation();
-                kpi.ContainerName = containerName;
-                kpi.ProviderType = 1; // PROV_RSA_FULL
-                kpi.KeySpec = 1; // AT_KEYEXCHANGE
-
-                CryptAlgorithmIdentifier sha256Identifier = new CryptAlgorithmIdentifier();
-                sha256Identifier.pszObjId = "1.2.840.113549.1.1.11";
-
-                certContext = NativeMethods.CertCreateSelfSignCertificate(
-                    providerContext,
-                    ref nameBlob,
-                    0,
-                    ref kpi,
-                    ref sha256Identifier,
-                    ref startSystemTime,
-                    ref endSystemTime,
-                    IntPtr.Zero);
-                Check(certContext != IntPtr.Zero);
-                dataHandle.Free();
-
-                certStore = NativeMethods.CertOpenStore(
-                    "Memory", // sz_CERT_STORE_PROV_MEMORY
-                    0,
-                    IntPtr.Zero,
-                    0x2000, // CERT_STORE_CREATE_NEW_FLAG
-                    IntPtr.Zero);
-                Check(certStore != IntPtr.Zero);
-
-                Check(NativeMethods.CertAddCertificateContextToStore(
-                    certStore,
-                    certContext,
-                    1, // CERT_STORE_ADD_NEW
-                    out storeCertContext));
-
-                NativeMethods.CertSetCertificateContextProperty(
-                    storeCertContext,
-                    2, // CERT_KEY_PROV_INFO_PROP_ID
-                    0,
-                    ref kpi);
-
-                CryptoApiBlob pfxBlob = new CryptoApiBlob();
-                Check(NativeMethods.PFXExportCertStoreEx(
-                    certStore,
-                    ref pfxBlob,
-                    passwordPtr,
-                    IntPtr.Zero,
-                    7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
-
-                pfxData = new byte[pfxBlob.DataLength];
-                dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned);
-                pfxBlob.Data = dataHandle.AddrOfPinnedObject();
-                Check(NativeMethods.PFXExportCertStoreEx(
-                    certStore,
-                    ref pfxBlob,
-                    passwordPtr,
-                    IntPtr.Zero,
-                    7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
-                dataHandle.Free();
-            }
-            finally
-            {
-                if (passwordPtr != IntPtr.Zero)
-                {
-                    Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr);
-                }
-
-                if (dataHandle.IsAllocated)
-                {
-                    dataHandle.Free();
-                }
-
-                if (certContext != IntPtr.Zero)
-                {
-                    NativeMethods.CertFreeCertificateContext(certContext);
-                }
-
-                if (storeCertContext != IntPtr.Zero)
-                {
-                    NativeMethods.CertFreeCertificateContext(storeCertContext);
-                }
-
-                if (certStore != IntPtr.Zero)
-                {
-                    NativeMethods.CertCloseStore(certStore, 0);
-                }
-
-                if (cryptKey != IntPtr.Zero)
-                {
-                    NativeMethods.CryptDestroyKey(cryptKey);
-                }
-
-                if (providerContext != IntPtr.Zero)
-                {
-                    NativeMethods.CryptReleaseContext(providerContext, 0);
-                    NativeMethods.CryptAcquireContextW(
-                        out providerContext,
-                        containerName,
-                        null,
-                        1, // PROV_RSA_FULL
-                        0x10); // CRYPT_DELETEKEYSET
-                }
-            }
-
-            return pfxData;
-        }
-
-        private static SystemTime ToSystemTime(DateTime dateTime)
-        {
-            long fileTime = dateTime.ToFileTime();
-            SystemTime systemTime;
-            Check(NativeMethods.FileTimeToSystemTime(ref fileTime, out systemTime));
-            return systemTime;
-        }
-
-        private static void Check(bool nativeCallSucceeded)
-        {
-            if (!nativeCallSucceeded)
-            {
-                int error = Marshal.GetHRForLastWin32Error();
-                Marshal.ThrowExceptionForHR(error);
-            }
-        }
-    }
-}

+ 2 - 14
MediaBrowser.ServerApplication/Networking/NetworkManager.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.IO;
+using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
 using System;
@@ -8,14 +7,13 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Runtime.InteropServices;
-using Emby.Common.Implementations.Networking;
 
 namespace MediaBrowser.ServerApplication.Networking
 {
     /// <summary>
     /// Class NetUtils
     /// </summary>
-    public class NetworkManager : BaseNetworkManager, INetworkManager
+    public class NetworkManager : Server.Startup.Common.Networking.NetworkManager
     {
         public NetworkManager(ILogger logger)
             : base(logger)
@@ -160,16 +158,6 @@ namespace MediaBrowser.ServerApplication.Networking
             });
         }
 
-        /// <summary>
-        /// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>.
-        /// </summary>
-        /// <param name="certificatePath">The path to generate the certificate.</param>
-        /// <param name="hostname">The common name for the certificate.</param>
-        public void GenerateSelfSignedSslCertificate(string certificatePath, string hostname)
-        {
-            CertificateGenerator.CreateSelfSignCertificatePfx(certificatePath, hostname, Logger);
-        }
-
         /// <summary>
         /// Gets the network prefix.
         /// </summary>

+ 12 - 10
MediaBrowser.WebDashboard/Api/DashboardService.cs

@@ -79,19 +79,19 @@ namespace MediaBrowser.WebDashboard.Api
     /// <summary>
     /// Class DashboardService
     /// </summary>
-    public class DashboardService : IService, IHasResultFactory
+    public class DashboardService : IService, IRequiresRequest
     {
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
         /// <value>The logger.</value>
-        public ILogger Logger { get; set; }
+        private readonly ILogger _logger;
 
         /// <summary>
         /// Gets or sets the HTTP result factory.
         /// </summary>
         /// <value>The HTTP result factory.</value>
-        public IHttpResultFactory ResultFactory { get; set; }
+        private readonly IHttpResultFactory _resultFactory;
 
         /// <summary>
         /// Gets or sets the request context.
@@ -120,7 +120,7 @@ namespace MediaBrowser.WebDashboard.Api
         /// <param name="appHost">The app host.</param>
         /// <param name="serverConfigurationManager">The server configuration manager.</param>
         /// <param name="fileSystem">The file system.</param>
-        public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, IAssemblyInfo assemblyInfo)
+        public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, IAssemblyInfo assemblyInfo, ILogger logger, IHttpResultFactory resultFactory)
         {
             _appHost = appHost;
             _serverConfigurationManager = serverConfigurationManager;
@@ -128,6 +128,8 @@ namespace MediaBrowser.WebDashboard.Api
             _localization = localization;
             _jsonSerializer = jsonSerializer;
             _assemblyInfo = assemblyInfo;
+            _logger = logger;
+            _resultFactory = resultFactory;
         }
 
         /// <summary>
@@ -159,7 +161,7 @@ namespace MediaBrowser.WebDashboard.Api
 
             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));
+                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();
@@ -203,7 +205,7 @@ namespace MediaBrowser.WebDashboard.Api
                 }
                 catch (Exception ex)
                 {
-                    Logger.ErrorException("Error getting plugin information from {0}", ex, p.GetType().Name);
+                    _logger.ErrorException("Error getting plugin information from {0}", ex, p.GetType().Name);
                     return null;
                 }
             })
@@ -212,7 +214,7 @@ namespace MediaBrowser.WebDashboard.Api
 
             configPages.AddRange(_appHost.Plugins.SelectMany(GetConfigPages));
 
-            return ResultFactory.GetOptimizedResult(Request, configPages);
+            return _resultFactory.GetOptimizedResult(Request, configPages);
         }
 
         private IEnumerable<Tuple<PluginPageInfo, IPlugin>> GetPluginPages()
@@ -280,7 +282,7 @@ namespace MediaBrowser.WebDashboard.Api
                 !contentType.StartsWith("font/", StringComparison.OrdinalIgnoreCase))
             {
                 var stream = await GetResourceStream(path, localizationCulture).ConfigureAwait(false);
-                return ResultFactory.GetResult(stream, contentType);
+                return _resultFactory.GetResult(stream, contentType);
             }
 
             TimeSpan? cacheDuration = null;
@@ -294,7 +296,7 @@ namespace MediaBrowser.WebDashboard.Api
 
             var cacheKey = (_appHost.ApplicationVersion.ToString() + (localizationCulture ?? string.Empty) + path).GetMD5();
 
-            return await ResultFactory.GetStaticResult(Request, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(path, localizationCulture)).ConfigureAwait(false);
+            return await _resultFactory.GetStaticResult(Request, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(path, localizationCulture)).ConfigureAwait(false);
         }
 
         private string GetLocalizationCulture()
@@ -318,7 +320,7 @@ namespace MediaBrowser.WebDashboard.Api
 
         private PackageCreator GetPackageCreator()
         {
-            return new PackageCreator(_fileSystem, _localization, Logger, _serverConfigurationManager, _jsonSerializer);
+            return new PackageCreator(_fileSystem, _localization, _logger, _serverConfigurationManager, _jsonSerializer);
         }
 
         private List<string> GetDeployIgnoreExtensions()