diff --git a/build/NuSpecs/build/UmbracoCms.targets b/build/NuSpecs/build/UmbracoCms.targets index 024d8af7ad..fde5b4ea81 100644 --- a/build/NuSpecs/build/UmbracoCms.targets +++ b/build/NuSpecs/build/UmbracoCms.targets @@ -1,6 +1,17 @@  + + + $(MSBuildThisFileDirectory)..\UmbracoFiles\ + + + + + + + + $(MSBuildThisFileDirectory)..\UmbracoFiles\ @@ -47,4 +58,4 @@ - \ No newline at end of file + diff --git a/src/Umbraco.Core/Persistence/PetaPoco.cs b/src/Umbraco.Core/Persistence/PetaPoco.cs index d55ad8fc14..916f187b5b 100644 --- a/src/Umbraco.Core/Persistence/PetaPoco.cs +++ b/src/Umbraco.Core/Persistence/PetaPoco.cs @@ -20,10 +20,12 @@ using System.Text; using System.Configuration; using System.Data.Common; using System.Data; +using System.Globalization; using System.Text.RegularExpressions; using System.Reflection; using System.Reflection.Emit; using System.Linq.Expressions; +using System.Threading; namespace Umbraco.Core.Persistence { @@ -1802,8 +1804,53 @@ namespace Umbraco.Core.Persistence return ObjectCache; } - static readonly ObjectCache ObjectCache = new MemoryCache("NPoco"); - + //static readonly ObjectCache ObjectCache = new MemoryCache("NPoco"); + private static readonly ObjectCache ObjectCache; + + // this should probably happen somewhere else...f + private static void FixCurrentCulture() + { + // get the current culture + var currentCulture = CultureInfo.CurrentCulture; + + // at the top of any culture should be the invariant culture - find it + var invariantCulture = currentCulture; + while (invariantCulture.Equals(CultureInfo.InvariantCulture) == false) + invariantCulture = invariantCulture.Parent; + + // now that invariant culture should be the same object as CultureInfo.InvariantCulture + // yet for some weird reason, sometimes it is not - and this breaks eg MemoryCache, + // because it ends up in PerformanceCounterLib.IsCustomCategory which does: + // + // CultureInfo culture = CultureInfo.CurrentCulture; + // while (culture != CultureInfo.InvariantCulture) + // { + // library = GetPerformanceCounterLib(machine, culture); + // if (library.IsCustomCategory(category)) + // return true; + // culture = culture.Parent; + // } + // + // ie a reference comparisons = enters an endless loop and hangs everything. + + if (ReferenceEquals(invariantCulture, CultureInfo.InvariantCulture)) + return; + + // so if it is not the same object, replace the culture by the "fixed" version of + // itself - this prevents MemoryCache from dying - but it is an ugly workaround and + // does not explain why we would have different CultureInfo objects + + var fixedCulture = CultureInfo.GetCultureInfo(currentCulture.Name); + Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = fixedCulture; + } + + static ManagedCache() + { + FixCurrentCulture(); + ObjectCache = new MemoryCache("NPoco"); + } + + } public class PocoData diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index da25bd0938..ba8b51fa5b 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -445,6 +445,9 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetAncestors(IContent content) { + //null check otherwise we get exceptions + if (content.Path.IsNullOrWhiteSpace()) return Enumerable.Empty(); + var ids = content.Path.Split(',').Where(x => x != Constants.System.Root.ToInvariantString() && x != content.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray(); if (ids.Any() == false) return new List(); diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContent.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContent.cs index 8ccf158034..e72290c163 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContent.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContent.cs @@ -8,7 +8,7 @@ namespace Umbraco.Tests.TestHelpers.Entities { public static Content CreateSimpleContent(IContentType contentType) { - var content = new Content("Home", -1, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0, Path = "-1" }; + var content = new Content("Home", -1, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 }; object obj = new { diff --git a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js index 56e0eb3041..2b757707ba 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js @@ -1,6 +1,6 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) // This http interceptor listens for authentication successes and failures - .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', function ($injector, queue, notifications) { + .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'requestInterceptorFilter', function ($injector, queue, notifications, requestInterceptorFilter) { return function(promise) { return promise.then( @@ -19,6 +19,19 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) return promise; }, function(originalResponse) { // Intercept failed requests + + //Here we'll check if we should ignore the error, this will be based on an original header set + var headers = originalResponse.config ? originalResponse.config.headers : {}; + if (headers["x-umb-ignore-error"] === "ignore") { + //exit/ignore + return promise; + } + var filtered = _.find(requestInterceptorFilter(), function(val) { + return originalResponse.config.url.indexOf(val) > 0; + }); + if (filtered) { + return promise; + } //A 401 means that the user is not logged in if (originalResponse.status === 401) { @@ -72,6 +85,10 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) }; }]) + .value('requestInterceptorFilter', function() { + return ["www.gravatar.com"]; + }) + // We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block. .config(['$httpProvider', function ($httpProvider) { $httpProvider.responseInterceptors.push('securityInterceptor'); diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/database.html b/src/Umbraco.Web.UI.Client/src/installer/steps/database.html index 0e9ebc7526..0cc7511f89 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/database.html +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/database.html @@ -42,7 +42,7 @@
- + Enter server domain or IP
diff --git a/src/Umbraco.Web.UI.Client/src/less/login.less b/src/Umbraco.Web.UI.Client/src/less/login.less index c94414df10..751ea8f3f0 100644 --- a/src/Umbraco.Web.UI.Client/src/less/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/login.less @@ -8,7 +8,7 @@ background-size: 30px 30px !important; color: @white; position: absolute; - z-index: 2000; + z-index: 10000; top: 0px; left: 0px; margin: 0 !Important; diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index 2e524fc480..a67fb5cb99 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -116,8 +116,30 @@ namespace Umbraco.Web.Models.Mapping { //map the IsChildOfListView (this is actually if it is a descendant of a list view!) //TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current - var ancesctorListView = content.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer); - display.IsChildOfListView = ancesctorListView != null; + if (content.HasIdentity) + { + var ancesctorListView = content.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer); + display.IsChildOfListView = ancesctorListView != null; + } + else + { + //it's new so it doesn't have a path, so we need to look this up by it's parent + ancestors + var parent = content.Parent(); + if (parent == null) + { + display.IsChildOfListView = false; + } + else if (parent.ContentType.IsContainer) + { + display.IsChildOfListView = true; + } + else + { + var ancesctorListView = parent.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer); + display.IsChildOfListView = ancesctorListView != null; + } + } + //map the tree node url if (HttpContext.Current != null) diff --git a/src/Umbraco.Web/Security/Identity/GetUserSecondsMiddleWare.cs b/src/Umbraco.Web/Security/Identity/GetUserSecondsMiddleWare.cs index d909ff76e2..f9b9fc0ca6 100644 --- a/src/Umbraco.Web/Security/Identity/GetUserSecondsMiddleWare.cs +++ b/src/Umbraco.Web/Security/Identity/GetUserSecondsMiddleWare.cs @@ -83,7 +83,7 @@ namespace Umbraco.Web.Security.Identity var cookieOptions = new CookieOptions { Path = "/", - Domain = _authOptions.CookieDomain, + Domain = _authOptions.CookieDomain ?? "FALSE", Expires = DateTime.Now.AddMinutes(_authOptions.LoginTimeoutMinutes), HttpOnly = true, Secure = _authOptions.CookieSecure == CookieSecureOption.Always