Pārlūkot izejas kodu

connect updates

Luke Pulverenti 10 gadi atpakaļ
vecāks
revīzija
5ca4d60c34
30 mainītis faili ar 190 papildinājumiem un 88 dzēšanām
  1. 1 1
      MediaBrowser.Api/System/SystemService.cs
  2. 1 1
      MediaBrowser.Api/UserService.cs
  3. 1 12
      MediaBrowser.Controller/Entities/AdultVideo.cs
  4. 1 9
      MediaBrowser.Controller/Entities/Movies/Movie.cs
  5. 1 8
      MediaBrowser.Controller/Entities/Trailer.cs
  6. 8 0
      MediaBrowser.Controller/Entities/Video.cs
  7. 5 0
      MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
  8. 28 6
      MediaBrowser.Controller/Net/AuthenticatedAttribute.cs
  9. 1 3
      MediaBrowser.Controller/Net/IAuthService.cs
  10. 5 0
      MediaBrowser.Controller/Playlists/Playlist.cs
  11. 6 0
      MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
  12. 6 0
      MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
  13. 22 0
      MediaBrowser.Model/ApiClient/ApiHelpers.cs
  14. 2 1
      MediaBrowser.Model/ApiClient/ConnectionState.cs
  15. 11 0
      MediaBrowser.Model/ApiClient/HttpResponseEventArgs.cs
  16. 1 1
      MediaBrowser.Model/ApiClient/IApiClient.cs
  17. 9 0
      MediaBrowser.Model/ApiClient/RemoteLogoutReason.cs
  18. 2 0
      MediaBrowser.Model/MediaBrowser.Model.csproj
  19. 18 2
      MediaBrowser.Providers/Manager/MetadataService.cs
  20. 34 24
      MediaBrowser.Providers/Manager/ProviderUtils.cs
  21. 2 2
      MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
  22. 1 1
      MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs
  23. 11 9
      MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
  24. 3 2
      MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
  25. 1 0
      MediaBrowser.WebDashboard/Api/PackageCreator.cs
  26. 3 0
      MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
  27. 2 2
      Nuget/MediaBrowser.Common.Internal.nuspec
  28. 1 1
      Nuget/MediaBrowser.Common.nuspec
  29. 1 1
      Nuget/MediaBrowser.Model.Signed.nuspec
  30. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec

+ 1 - 1
MediaBrowser.Api/System/SystemService.cs

@@ -19,7 +19,7 @@ namespace MediaBrowser.Api.System
     /// Class GetSystemInfo
     /// </summary>
     [Route("/System/Info", "GET", Summary = "Gets information about the server")]
-    [Authenticated]
+    [Authenticated(EscapeParentalControl = true)]
     public class GetSystemInfo : IReturn<SystemInfo>
     {
 

+ 1 - 1
MediaBrowser.Api/UserService.cs

@@ -43,7 +43,7 @@ namespace MediaBrowser.Api
     /// Class GetUser
     /// </summary>
     [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
-    [Authenticated]
+    [Authenticated(EscapeParentalControl = true)]
     public class GetUser : IReturn<UserDto>
     {
         /// <summary>

+ 1 - 12
MediaBrowser.Controller/Entities/AdultVideo.cs

@@ -5,19 +5,8 @@ using System.Collections.Generic;
 namespace MediaBrowser.Controller.Entities
 {
     [Obsolete]
-    public class AdultVideo : Video, IHasProductionLocations, IHasPreferredMetadataLanguage, IHasTaglines
+    public class AdultVideo : Video, IHasProductionLocations, IHasTaglines
     {
-        /// <summary>
-        /// Gets or sets the preferred metadata language.
-        /// </summary>
-        /// <value>The preferred metadata language.</value>
-        public string PreferredMetadataLanguage { get; set; }
-
-        /// <summary>
-        /// Gets or sets the preferred metadata country code.
-        /// </summary>
-        /// <value>The preferred metadata country code.</value>
-        public string PreferredMetadataCountryCode { get; set; }
         public List<string> ProductionLocations { get; set; }
 
         public List<string> Taglines { get; set; }

+ 1 - 9
MediaBrowser.Controller/Entities/Movies/Movie.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities.Movies
     /// <summary>
     /// Class Movie
     /// </summary>
-    public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
+    public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
     {
         public List<Guid> SpecialFeatureIds { get; set; }
 
@@ -30,14 +30,6 @@ namespace MediaBrowser.Controller.Entities.Movies
         [IgnoreDataMember]
         public List<Guid> BoxSetIdList { get; set; }
 
-        /// <summary>
-        /// Gets or sets the preferred metadata country code.
-        /// </summary>
-        /// <value>The preferred metadata country code.</value>
-        public string PreferredMetadataCountryCode { get; set; }
-
-        public string PreferredMetadataLanguage { get; set; }
-
         public Movie()
         {
             SpecialFeatureIds = new List<Guid>();

+ 1 - 8
MediaBrowser.Controller/Entities/Trailer.cs

@@ -12,19 +12,12 @@ namespace MediaBrowser.Controller.Entities
     /// <summary>
     /// Class Trailer
     /// </summary>
-    public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasPreferredMetadataLanguage, IHasMetascore, IHasLookupInfo<TrailerInfo>
+    public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
     {
         public List<Guid> SoundtrackIds { get; set; }
 
-        public string PreferredMetadataLanguage { get; set; }
         public List<string> ProductionLocations { get; set; }
 
-        /// <summary>
-        /// Gets or sets the preferred metadata country code.
-        /// </summary>
-        /// <value>The preferred metadata country code.</value>
-        public string PreferredMetadataCountryCode { get; set; }
-
         public Trailer()
         {
             RemoteTrailers = new List<MediaUrl>();

+ 8 - 0
MediaBrowser.Controller/Entities/Video.cs

@@ -25,6 +25,7 @@ namespace MediaBrowser.Controller.Entities
         ISupportsPlaceHolders,
         IHasMediaSources,
         IHasShortOverview,
+        IHasPreferredMetadataLanguage,
         IThemeMedia
     {
         public bool IsMultiPart { get; set; }
@@ -43,6 +44,13 @@ namespace MediaBrowser.Controller.Entities
         public string ShortOverview { get; set; }
         public ExtraType ExtraType { get; set; }
 
+        /// <summary>
+        /// Gets or sets the preferred metadata country code.
+        /// </summary>
+        /// <value>The preferred metadata country code.</value>
+        public string PreferredMetadataCountryCode { get; set; }
+        public string PreferredMetadataLanguage { get; set; }
+
         /// <summary>
         /// Gets or sets the timestamp.
         /// </summary>

+ 5 - 0
MediaBrowser.Controller/LiveTv/LiveTvChannel.cs

@@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.LiveTv
             }
         }
 
+        public override bool IsSaveLocalMetadataEnabled()
+        {
+            return true;
+        }
+
         /// <summary>
         /// Gets or sets the number.
         /// </summary>

+ 28 - 6
MediaBrowser.Controller/Net/AuthenticatedAttribute.cs

@@ -1,10 +1,11 @@
 using ServiceStack.Web;
 using System;
+using System.Collections.Generic;
 using System.Linq;
 
 namespace MediaBrowser.Controller.Net
 {
-    public class AuthenticatedAttribute : Attribute, IHasRequestFilter
+    public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticated
     {
         public IAuthService AuthService { get; set; }
 
@@ -14,8 +15,18 @@ namespace MediaBrowser.Controller.Net
         /// <value><c>true</c> if [allow local]; otherwise, <c>false</c>.</value>
         public bool AllowLocal { get; set; }
 
+        /// <summary>
+        /// Gets or sets the roles.
+        /// </summary>
+        /// <value>The roles.</value>
         public string Roles { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether [escape parental control].
+        /// </summary>
+        /// <value><c>true</c> if [escape parental control]; otherwise, <c>false</c>.</value>
+        public bool EscapeParentalControl { get; set; }
+
         /// <summary>
         /// The request filter is executed before the service.
         /// </summary>
@@ -24,11 +35,7 @@ namespace MediaBrowser.Controller.Net
         /// <param name="requestDto">The request DTO</param>
         public void RequestFilter(IRequest request, IResponse response, object requestDto)
         {
-            var roles = (Roles ?? string.Empty).Split(',')
-                .Where(i => !string.IsNullOrWhiteSpace(i))
-                .ToArray();
-
-            AuthService.Authenticate(request, response, requestDto, AllowLocal, roles);
+            AuthService.Authenticate(request, response, requestDto, this);
         }
 
         /// <summary>
@@ -50,5 +57,20 @@ namespace MediaBrowser.Controller.Net
         {
             get { return 0; }
         }
+
+
+        public IEnumerable<string> GetRoles()
+        {
+            return (Roles ?? string.Empty).Split(',')
+                .Where(i => !string.IsNullOrWhiteSpace(i));
+        }
+    }
+
+    public interface IAuthenticated
+    {
+        bool EscapeParentalControl { get; }
+
+        bool AllowLocal { get; }
+        IEnumerable<string> GetRoles();
     }
 }

+ 1 - 3
MediaBrowser.Controller/Net/IAuthService.cs

@@ -1,5 +1,4 @@
 using ServiceStack.Web;
-using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.Net
 {
@@ -8,7 +7,6 @@ namespace MediaBrowser.Controller.Net
         void Authenticate(IRequest request, 
             IResponse response, 
             object requestDto, 
-            bool allowLocal, 
-            string[] roles);
+            IAuthenticated authAttribtues);
     }
 }

+ 5 - 0
MediaBrowser.Controller/Playlists/Playlist.cs

@@ -33,6 +33,11 @@ namespace MediaBrowser.Controller.Playlists
             }
         }
 
+        public override bool IsSaveLocalMetadataEnabled()
+        {
+            return true;
+        }
+
         public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             return GetPlayableItems(user);

+ 6 - 0
MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj

@@ -74,6 +74,9 @@
     <Compile Include="..\MediaBrowser.Model\ApiClient\ApiClientExtensions.cs">
       <Link>ApiClient\ApiClientExtensions.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\ApiClient\ApiHelpers.cs">
+      <Link>ApiClient\ApiHelpers.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\ApiClient\ConnectionMode.cs">
       <Link>ApiClient\ConnectionMode.cs</Link>
     </Compile>
@@ -104,6 +107,9 @@
     <Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
       <Link>ApiClient\IServerEvents.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\ApiClient\RemoteLogoutReason.cs">
+      <Link>ApiClient\RemoteLogoutReason.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\ApiClient\ServerCredentials.cs">
       <Link>ApiClient\ServerCredentials.cs</Link>
     </Compile>

+ 6 - 0
MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj

@@ -54,6 +54,9 @@
     <Compile Include="..\mediabrowser.model\activity\ActivityLogEntry.cs">
       <Link>Activity\ActivityLogEntry.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\ApiClient\ApiHelpers.cs">
+      <Link>ApiClient\ApiHelpers.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\ApiClient\ConnectionMode.cs">
       <Link>ApiClient\ConnectionMode.cs</Link>
     </Compile>
@@ -69,6 +72,9 @@
     <Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
       <Link>ApiClient\IServerEvents.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\ApiClient\RemoteLogoutReason.cs">
+      <Link>ApiClient\RemoteLogoutReason.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\ApiClient\ServerCredentials.cs">
       <Link>ApiClient\ServerCredentials.cs</Link>
     </Compile>

+ 22 - 0
MediaBrowser.Model/ApiClient/ApiHelpers.cs

@@ -0,0 +1,22 @@
+using System;
+
+namespace MediaBrowser.Model.ApiClient
+{
+    public static class ApiHelpers
+    {
+        /// <summary>
+        /// Gets the name of the slug.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <returns>System.String.</returns>
+        public static string GetSlugName(string name)
+        {
+            if (string.IsNullOrEmpty(name))
+            {
+                throw new ArgumentNullException("name");
+            }
+
+            return name.Replace('/', '-').Replace('?', '-').Replace('&', '-');
+        }
+    }
+}

+ 2 - 1
MediaBrowser.Model/ApiClient/ConnectionState.cs

@@ -5,6 +5,7 @@ namespace MediaBrowser.Model.ApiClient
         Unavailable = 1,
         ServerSignIn = 2,
         SignedIn = 3,
-        ServerSelection = 4
+        ServerSelection = 4,
+        ConnectSignIn = 5
     }
 }

+ 11 - 0
MediaBrowser.Model/ApiClient/HttpResponseEventArgs.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Net;
 
 namespace MediaBrowser.Model.ApiClient
@@ -18,5 +19,15 @@ namespace MediaBrowser.Model.ApiClient
         /// </summary>
         /// <value>The status code.</value>
         public HttpStatusCode StatusCode { get; set; }
+        /// <summary>
+        /// Gets or sets the headers.
+        /// </summary>
+        /// <value>The headers.</value>
+        public Dictionary<string, string> Headers { get; set; }
+
+        public HttpResponseEventArgs()
+        {
+            Headers = new Dictionary<string, string>();
+        }
     }
 }

+ 1 - 1
MediaBrowser.Model/ApiClient/IApiClient.cs

@@ -32,7 +32,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <summary>
         /// Occurs when [remote logged out].
         /// </summary>
-        event EventHandler<EventArgs> RemoteLoggedOut;
+        event EventHandler<GenericEventArgs<RemoteLogoutReason>> RemoteLoggedOut;
 
         /// <summary>
         /// Occurs when [authenticated].

+ 9 - 0
MediaBrowser.Model/ApiClient/RemoteLogoutReason.cs

@@ -0,0 +1,9 @@
+
+namespace MediaBrowser.Model.ApiClient
+{
+    public enum RemoteLogoutReason
+    {
+        GeneralAccesError = 0,
+        ParentalControlRestriction = 1
+    }
+}

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

@@ -60,6 +60,7 @@
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     <Compile Include="Activity\ActivityLogEntry.cs" />
+    <Compile Include="ApiClient\ApiHelpers.cs" />
     <Compile Include="ApiClient\ConnectionMode.cs" />
     <Compile Include="ApiClient\ConnectionResult.cs" />
     <Compile Include="ApiClient\ConnectionState.cs" />
@@ -71,6 +72,7 @@
     <Compile Include="ApiClient\IDevice.cs" />
     <Compile Include="ApiClient\IServerEvents.cs" />
     <Compile Include="ApiClient\GeneralCommandEventArgs.cs" />
+    <Compile Include="ApiClient\RemoteLogoutReason.cs" />
     <Compile Include="ApiClient\ServerCredentials.cs" />
     <Compile Include="ApiClient\ServerDiscoveryInfo.cs" />
     <Compile Include="ApiClient\ServerInfo.cs" />

+ 18 - 2
MediaBrowser.Providers/Manager/MetadataService.cs

@@ -350,6 +350,7 @@ namespace MediaBrowser.Providers.Manager
             {
                 var remoteResult = await ExecuteRemoteProviders(item, temp, logName, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), cancellationToken)
                     .ConfigureAwait(false);
+
                 refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType;
                 refreshResult.Status = remoteResult.Status;
                 refreshResult.ErrorMessage = remoteResult.ErrorMessage;
@@ -359,8 +360,9 @@ namespace MediaBrowser.Providers.Manager
 
             var hasLocalMetadata = false;
             var userDataList = new List<UserItemData>();
+            var localProviders = providers.OfType<ILocalMetadataProvider<TItemType>>().ToList();
 
-            foreach (var provider in providers.OfType<ILocalMetadataProvider<TItemType>>())
+            foreach (var provider in localProviders)
             {
                 var providerName = provider.GetType().Name;
                 Logger.Debug("Running {0} for {1}", providerName, logName);
@@ -428,6 +430,16 @@ namespace MediaBrowser.Providers.Manager
                 successfulProviderCount += remoteResult.Successes;
             }
 
+            // If no local providers and doing a full refresh, take data from item itself
+            if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh &&
+                localProviders.Count == 0 &&
+                refreshResult.UpdateType > ItemUpdateType.None)
+            {
+                // TODO: If the new metadata from above has some blank data, this
+                // can cause old data to get filled into those empty fields
+                MergeData(item, temp, new List<MetadataFields>(), false, true);
+            }
+
             if (refreshResult.UpdateType > ItemUpdateType.None)
             {
                 MergeData(temp, item, item.LockedFields, true, true);
@@ -598,7 +610,11 @@ namespace MediaBrowser.Providers.Manager
             }
         }
 
-        protected abstract void MergeData(TItemType source, TItemType target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings);
+        protected abstract void MergeData(TItemType source, 
+            TItemType target, 
+            List<MetadataFields> lockedFields, 
+            bool replaceData, 
+            bool mergeMetadataSettings);
 
         public virtual int Order
         {

+ 34 - 24
MediaBrowser.Providers/Manager/ProviderUtils.cs

@@ -8,7 +8,11 @@ namespace MediaBrowser.Providers.Manager
 {
     public static class ProviderUtils
     {
-        public static void MergeBaseItemData(BaseItem source, BaseItem target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
+        public static void MergeBaseItemData(BaseItem source, 
+            BaseItem target, 
+            List<MetadataFields> lockedFields, 
+            bool replaceData, 
+            bool mergeMetadataSettings)
         {
             if (!lockedFields.Contains(MetadataFields.Name))
             {
@@ -191,36 +195,42 @@ namespace MediaBrowser.Providers.Manager
 
             if (mergeMetadataSettings)
             {
-                target.ForcedSortName = source.ForcedSortName;
-                target.LockedFields = source.LockedFields;
-                target.IsLocked = source.IsLocked;
-                target.DisplayMediaType = source.DisplayMediaType;
+                MergeMetadataSettings(source, target);
+            }
+        }
 
-                // Grab the value if it's there, but if not then don't overwrite the default
-                if (source.DateCreated != default(DateTime))
-                {
-                    target.DateCreated = source.DateCreated;
-                }
+        public static void MergeMetadataSettings(BaseItem source,
+           BaseItem target)
+        {
+            target.ForcedSortName = source.ForcedSortName;
+            target.LockedFields = source.LockedFields;
+            target.IsLocked = source.IsLocked;
+            target.DisplayMediaType = source.DisplayMediaType;
 
-                var sourceHasLanguageSettings = source as IHasPreferredMetadataLanguage;
-                var targetHasLanguageSettings = target as IHasPreferredMetadataLanguage;
+            // Grab the value if it's there, but if not then don't overwrite the default
+            if (source.DateCreated != default(DateTime))
+            {
+                target.DateCreated = source.DateCreated;
+            }
 
-                if (sourceHasLanguageSettings != null && targetHasLanguageSettings != null)
-                {
-                    targetHasLanguageSettings.PreferredMetadataCountryCode = sourceHasLanguageSettings.PreferredMetadataCountryCode;
-                    targetHasLanguageSettings.PreferredMetadataLanguage = sourceHasLanguageSettings.PreferredMetadataLanguage;
-                }
+            var sourceHasLanguageSettings = source as IHasPreferredMetadataLanguage;
+            var targetHasLanguageSettings = target as IHasPreferredMetadataLanguage;
 
-                var sourceHasDisplayOrder = source as IHasDisplayOrder;
-                var targetHasDisplayOrder = target as IHasDisplayOrder;
+            if (sourceHasLanguageSettings != null && targetHasLanguageSettings != null)
+            {
+                targetHasLanguageSettings.PreferredMetadataCountryCode = sourceHasLanguageSettings.PreferredMetadataCountryCode;
+                targetHasLanguageSettings.PreferredMetadataLanguage = sourceHasLanguageSettings.PreferredMetadataLanguage;
+            }
 
-                if (sourceHasDisplayOrder != null && targetHasDisplayOrder != null)
-                {
-                    targetHasDisplayOrder.DisplayOrder = sourceHasDisplayOrder.DisplayOrder;
-                }
+            var sourceHasDisplayOrder = source as IHasDisplayOrder;
+            var targetHasDisplayOrder = target as IHasDisplayOrder;
+
+            if (sourceHasDisplayOrder != null && targetHasDisplayOrder != null)
+            {
+                targetHasDisplayOrder.DisplayOrder = sourceHasDisplayOrder.DisplayOrder;
             }
         }
-
+        
         private static void MergeShortOverview(BaseItem source, BaseItem target, List<MetadataFields> lockedFields, bool replaceData)
         {
             var sourceHasShortOverview = source as IHasShortOverview;

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

@@ -235,14 +235,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                 {
                     return;
                 }
-
+                
                 var errorResponse = new ErrorResponse
                 {
                     ResponseStatus = new ResponseStatus
                     {
                         ErrorCode = ex.GetType().GetOperationName(),
                         Message = ex.Message,
-                        StackTrace = ex.StackTrace,
+                        StackTrace = ex.StackTrace
                     }
                 };
 

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

@@ -94,7 +94,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// </summary>
         /// <param name="inString">The in string.</param>
         /// <returns>System.String.</returns>
-        private static string RemoveControlCharacters(string inString)
+        public static string RemoveControlCharacters(string inString)
         {
             if (inString == null) return null;
 

+ 11 - 9
MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs

@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Session;
@@ -45,8 +44,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
         public void Authenticate(IRequest request,
             IResponse response,
             object requestDto,
-            bool allowLocal,
-            string[] roles)
+            IAuthenticated authAttribtues)
         {
             if (HostContext.HasValidAuthSecret(request))
                 return;
@@ -54,16 +52,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
             //ExecuteBasic(req, res, requestDto); //first check if session is authenticated
             //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed)
 
-            ValidateUser(request, allowLocal, roles);
+            ValidateUser(request, response, authAttribtues);
         }
 
-        private void ValidateUser(IRequest req, bool allowLocal,
-            IEnumerable<string> roles)
+        private void ValidateUser(IRequest req, IResponse response, IAuthenticated authAttribtues)
         {
             // This code is executed before the service
             var auth = AuthorizationContext.GetAuthorizationInfo(req);
 
-            if (!allowLocal || !req.IsLocal)
+            if (!authAttribtues.AllowLocal || !req.IsLocal)
             {
                 if (!string.IsNullOrWhiteSpace(auth.Token) ||
                     !_config.Configuration.InsecureApps2.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase))
@@ -91,12 +88,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
                     throw new AuthenticationException("User account has been disabled.");
                 }
 
-                if (!user.Configuration.IsAdministrator && !user.IsParentalScheduleAllowed())
+                if (!user.Configuration.IsAdministrator &&
+                    !authAttribtues.EscapeParentalControl &&
+                    !user.IsParentalScheduleAllowed())
                 {
+                    response.AddHeader("X-Application-Error-Code", "ParentalControl");
                     throw new AuthenticationException("This user account is not allowed access at this time.");
                 }
             }
 
+            var roles = authAttribtues.GetRoles().ToList();
+
             if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
             {
                 if (user == null || !user.Configuration.IsAdministrator)

+ 3 - 2
MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json

@@ -619,6 +619,7 @@
     "MessageInvitationSentToNewUser": "An email has been sent to {0} inviting them to sign up with Media Browser.",
     "HeaderConnectionFailure": "Connection Failure",
     "MessageUnableToConnectToServer": "We're unable to connect to the selected right now. Please try again later.",
-    "ButtonSelectServer":  "Select server",
-    "MessagePluginConfigurationRequiresLocalAccess": "To configure this plugin please sign in to your local server directly."
+    "ButtonSelectServer": "Select server",
+    "MessagePluginConfigurationRequiresLocalAccess": "To configure this plugin please sign in to your local server directly.",
+    "MessageLoggedOutParentalControl": "Access is currently restricted. Please try again later."
 }

+ 1 - 0
MediaBrowser.WebDashboard/Api/PackageCreator.cs

@@ -265,6 +265,7 @@ namespace MediaBrowser.WebDashboard.Api
                 "thirdparty/apiclient/md5.js",
                 "thirdparty/apiclient/sha1.js",
                 "thirdparty/apiclient/store.js",
+                "thirdparty/apiclient/network.js",
                 "thirdparty/apiclient/device.js",
                 "thirdparty/apiclient/credentials.js",
                 "thirdparty/apiclient/mediabrowser.apiclient.js",

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

@@ -920,6 +920,9 @@
     <Content Include="dashboard-ui\thirdparty\apiclient\credentials.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="dashboard-ui\thirdparty\apiclient\network.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\thirdparty\apiclient\sha1.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>

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

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

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

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

+ 1 - 1
Nuget/MediaBrowser.Model.Signed.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Model.Signed</id>
-        <version>3.0.501</version>
+        <version>3.0.502</version>
         <title>MediaBrowser.Model - Signed Edition</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

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

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.501</version>
+        <version>3.0.502</version>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.501" />
+            <dependency id="MediaBrowser.Common" version="3.0.502" />
         </dependencies>
     </metadata>
     <files>