From d8811d6b46782c70edf655eaef18807377ebaa33 Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Wed, 10 May 2017 13:35:28 -0700 Subject: [PATCH 01/12] Refactored code for FIPS compliance support. Added/converted to using a more generic Hash() method instead of directly using MD5. --- .../Security/BackOfficeUserStore.cs | 2 +- src/Umbraco.Core/StringExtensions.cs | 100 +++++++++--------- src/Umbraco.Web/Editors/GravatarController.cs | 9 ++ .../Models/Mapping/UserModelMapper.cs | 4 +- src/Umbraco.Web/UmbracoHelper.cs | 36 ++++--- .../umbraco.presentation/library.cs | 3 +- .../plugins/tinymce3/GzipCompressor.cs | 12 +-- .../AzureLocalStorageDirectory.cs | 2 +- .../RazorCore/RazorMacroEngine.cs | 6 +- .../webcontrol/plugin/GzipCompressor.cs | 12 +-- 10 files changed, 102 insertions(+), 84 deletions(-) diff --git a/src/Umbraco.Core/Security/BackOfficeUserStore.cs b/src/Umbraco.Core/Security/BackOfficeUserStore.cs index 889c7004d7..7d5774c870 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserStore.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserStore.cs @@ -494,7 +494,7 @@ namespace Umbraco.Core.Security //the stamp cannot be null, so if it is currently null then we'll just return a hash of the password return Task.FromResult(user.SecurityStamp.IsNullOrWhiteSpace() - ? user.PasswordHash.ToMd5() + ? user.PasswordHash.GenerateHash() : user.SecurityStamp); } diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index 225ac99ff7..f540305325 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -701,67 +701,72 @@ namespace Umbraco.Core return val; } + /// + /// Generates a hash of a string based on the FIPS compliance setting. + /// + /// Referrs to itself + /// The hashed string + public static string GenerateHash(this string str) + { + return CryptoConfig.AllowOnlyFipsAlgorithms + ? str.ToSHA1() + : str.ToMd5(); + } + /// /// Converts the string to MD5 /// - /// referrs to itself - /// the md5 hashed string + /// Referrs to itself + /// The MD5 hashed string public static string ToMd5(this string stringToConvert) { - //create an instance of the MD5CryptoServiceProvider - var md5Provider = new MD5CryptoServiceProvider(); - - //convert our string into byte array - var byteArray = Encoding.UTF8.GetBytes(stringToConvert); - - //get the hashed values created by our MD5CryptoServiceProvider - var hashedByteArray = md5Provider.ComputeHash(byteArray); - - //create a StringBuilder object - var stringBuilder = new StringBuilder(); - - //loop to each each byte - foreach (var b in hashedByteArray) - { - //append it to our StringBuilder - stringBuilder.Append(b.ToString("x2").ToLower()); - } - - //return the hashed value - return stringBuilder.ToString(); + return stringToConvert.GenerateHash("MD5"); } /// /// Converts the string to SHA1 /// /// referrs to itself - /// the md5 hashed string + /// The SHA1 hashed string public static string ToSHA1(this string stringToConvert) { - //create an instance of the SHA1CryptoServiceProvider - var md5Provider = new SHA1CryptoServiceProvider(); - - //convert our string into byte array - var byteArray = Encoding.UTF8.GetBytes(stringToConvert); - - //get the hashed values created by our SHA1CryptoServiceProvider - var hashedByteArray = md5Provider.ComputeHash(byteArray); - - //create a StringBuilder object - var stringBuilder = new StringBuilder(); - - //loop to each each byte - foreach (var b in hashedByteArray) - { - //append it to our StringBuilder - stringBuilder.Append(b.ToString("x2").ToLower()); - } - - //return the hashed value - return stringBuilder.ToString(); + return stringToConvert.GenerateHash("SHA1"); } + /// Generate a hash of a string based on the hashType passed in + /// + /// Referrs to itself + /// String with the hash type. See remarks section of the CryptoConfig Class in MSDN docs for a list of possible values. + /// The hashed string + private static string GenerateHash(this string str, string hashType) + { + //create an instance of the correct hashing provider based on the type passed in + var hasher = HashAlgorithm.Create(hashType); + if (hasher == null) throw new InvalidOperationException("No hashing type found by name " + hashType); + using (hasher) + { + //convert our string into byte array + var byteArray = Encoding.UTF8.GetBytes(str); + + //get the hashed values created by our selected provider + var hashedByteArray = hasher.ComputeHash(byteArray); + + //create a StringBuilder object + var stringBuilder = new StringBuilder(); + + //loop to each each byte + foreach (var b in hashedByteArray) + { + //append it to our StringBuilder + stringBuilder.Append(b.ToString("x2").ToLower()); + } + + //return the hashed value + return stringBuilder.ToString(); + } + } + /// /// Decodes a string that was encoded with UrlTokenEncode /// @@ -1465,10 +1470,7 @@ namespace Umbraco.Core /// internal static Guid ToGuid(this string text) { - var md5 = MD5.Create(); - byte[] myStringBytes = Encoding.ASCII.GetBytes(text); - byte[] hash = md5.ComputeHash(myStringBytes); - return new Guid(hash); + return new Guid(text.GenerateHash()); } } } diff --git a/src/Umbraco.Web/Editors/GravatarController.cs b/src/Umbraco.Web/Editors/GravatarController.cs index f1e184dce7..23c4a731c2 100644 --- a/src/Umbraco.Web/Editors/GravatarController.cs +++ b/src/Umbraco.Web/Editors/GravatarController.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Security.Cryptography; using Umbraco.Core; using Umbraco.Web.Mvc; @@ -13,6 +14,14 @@ namespace Umbraco.Web.Editors { public string GetCurrentUserGravatarUrl() { + // If FIPS is required, never check the Gravatar service as it only supports MD5 hashing. + // Unfortunately, if the FIPS setting is enabled on Windows, using MD5 will throw an exception + // and the website will not run. + if (CryptoConfig.AllowOnlyFipsAlgorithms) + { + return null; + } + var userService = Services.UserService; var user = userService.GetUserById(UmbracoContext.Security.CurrentUser.Id); var gravatarHash = user.Email.ToMd5(); diff --git a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs index 72093b19a8..eedc2cafca 100644 --- a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.GetUserCulture(applicationContext.Services.TextService))) .ForMember( detail => detail.EmailHash, - opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().ToMd5())) + opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().GenerateHash())) .ForMember(detail => detail.SecondsUntilTimeout, opt => opt.Ignore()); config.CreateMap() @@ -35,7 +35,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(detail => detail.AllowedSections, opt => opt.MapFrom(user => user.AllowedSections)) .ForMember( detail => detail.EmailHash, - opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().ToMd5())) + opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().GenerateHash())) .ForMember(detail => detail.SecondsUntilTimeout, opt => opt.Ignore()); config.CreateMap() diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 5befbda7cf..b2d6539b67 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -1238,20 +1238,30 @@ namespace Umbraco.Web return _stringUtilities.ReplaceLineBreaksForHtml(text); } - /// - /// Returns an MD5 hash of the string specified - /// - /// The text to create a hash from - /// Md5 has of the string - public string CreateMd5Hash(string text) - { - return text.ToMd5(); - } + /// + /// Returns an MD5 hash of the string specified + /// + /// The text to create a hash from + /// Md5 hash of the string + public string CreateMd5Hash(string text) + { + return text.ToMd5(); + } - /// - /// Strips all html tags from a given string, all contents of the tags will remain. - /// - public HtmlString StripHtml(IHtmlString html, params string[] tags) + /// + /// Returns a FIPS compliant hash of the string specified + /// + /// The text to create a hash from + /// hash of the string + public string CreateHash(string text) + { + return text.GenerateHash(); + } + + /// + /// Strips all html tags from a given string, all contents of the tags will remain. + /// + public HtmlString StripHtml(IHtmlString html, params string[] tags) { return StripHtml(html.ToHtmlString(), tags); } diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index 8bd94aa5b6..f728cd05ac 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -663,7 +663,8 @@ namespace umbraco /// Md5 has of the string public static string md5(string text) { - return text.ToMd5(); + //return text.ToMd5(); + return text.GenerateHash(); } /// diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs index d03dca1d6d..a06df51f5e 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs @@ -12,6 +12,7 @@ using System.IO; using System.IO.Compression; using System.Security.Cryptography; using System.Text; +using Umbraco.Core; namespace umbraco.presentation.plugins.tinymce3 { @@ -91,7 +92,7 @@ namespace umbraco.presentation.plugins.tinymce3 key += item.Data; } - key = MD5(key); + key = Hash(key); if (this.NoCompression) { this.SendPlainText(key, to_stream); return; @@ -224,12 +225,9 @@ namespace umbraco.presentation.plugins.tinymce3 } } - private string MD5(string str) { - MD5 md5 = new MD5CryptoServiceProvider(); - byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(str)); - str = BitConverter.ToString(result); - - return str.Replace("-", ""); + private string Hash(string str) + { + return str.GenerateHash(); } #endregion diff --git a/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs b/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs index 56d1b414c5..72a894f32f 100644 --- a/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs +++ b/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs @@ -16,7 +16,7 @@ namespace UmbracoExamine.LocalStorage { public DirectoryInfo GetLocalStorageDirectory(NameValueCollection config, string configuredPath) { - var appDomainHash = HttpRuntime.AppDomainAppId.ToMd5(); + var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash(); var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "LuceneDir", //include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back // to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not diff --git a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs index e3c7a22bd0..cddf6bc5dd 100644 --- a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs +++ b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs @@ -26,8 +26,8 @@ namespace umbraco.MacroEngines return "~/" + physicalPath; } - public string GetMd5(string text) { - return text.ToMd5(); + public string GetHash(string text) { + return text.GenerateHash(); } /// @@ -145,7 +145,7 @@ namespace umbraco.MacroEngines //Get Rid Of Whitespace From Start/End razorSyntax = razorSyntax.Trim(); //Use MD5 as a cache key - var syntaxMd5 = GetMd5(razorSyntax); + var syntaxMd5 = GetHash(razorSyntax); var fileName = "inline-" + syntaxMd5 + "." + scriptLanguage; return CreateTemporaryRazorFile(razorSyntax, fileName, true); } diff --git a/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs b/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs index cbd2fc24d8..d84453fa03 100644 --- a/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs +++ b/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs @@ -12,6 +12,7 @@ using System.IO; using System.IO.Compression; using System.Security.Cryptography; using System.Text; +using Umbraco.Core; namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin { @@ -93,7 +94,7 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin key += item.Data; } - key = MD5(key); + key = Hash(key); if (this.NoCompression) { this.SendPlainText(key, to_stream); return; @@ -226,12 +227,9 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin } } - private string MD5(string str) { - MD5 md5 = new MD5CryptoServiceProvider(); - byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(str)); - str = BitConverter.ToString(result); - - return str.Replace("-", ""); + private string Hash(string str) + { + return str.GenerateHash(); } #endregion From fead30db386afc99ad63929a07958f6b105d6c18 Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Wed, 10 May 2017 15:49:03 -0700 Subject: [PATCH 02/12] Removed commented code for hash algorithm refactoring --- .../umbraco/plugins/tinymce3/GzipCompressor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs index a06df51f5e..c9df806242 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs @@ -228,6 +228,7 @@ namespace umbraco.presentation.plugins.tinymce3 private string Hash(string str) { return str.GenerateHash(); + } #endregion From b55d065d452f42300401e6cc3b5b7d1e9337569c Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Thu, 11 May 2017 09:17:56 -0700 Subject: [PATCH 03/12] Update to mark some methods as Obsolete and not seen by the VS editor --- src/Umbraco.Web/UmbracoHelper.cs | 7 +++++-- src/Umbraco.Web/umbraco.presentation/library.cs | 17 +++++++++++++++-- .../developer/Packages/installer.aspx.cs | 2 +- .../RazorCore/RazorMacroEngine.cs | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index b2d6539b67..8a4f221ec4 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -1243,16 +1243,19 @@ namespace Umbraco.Web /// /// The text to create a hash from /// Md5 hash of the string + [Obsolete("Please use the CreateHash method instead. This may be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] public string CreateMd5Hash(string text) { return text.ToMd5(); } /// - /// Returns a FIPS compliant hash of the string specified + /// Generates a hash based on the text string passed in. This method will detect the + /// security requirements (is FIPS enabled) and return an appropriate hash. /// /// The text to create a hash from - /// hash of the string + /// Hash of the text string public string CreateHash(string text) { return text.GenerateHash(); diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index f728cd05ac..38b8b1b95d 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; @@ -660,10 +661,22 @@ namespace umbraco /// Returns an MD5 hash of the string specified /// /// The text to create a hash from - /// Md5 has of the string + /// Md5 hash of the string + [Obsolete("Please use the CreateHash method instead. This may be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] public static string md5(string text) { - //return text.ToMd5(); + return text.ToMd5(); + } + + /// + /// Generates a hash based on the text string passed in. This method will detect the + /// security requirements (is FIPS enabled) and return an appropriate hash. + /// + /// The text to create a hash from + /// hash of the string + public static string CreateHash(string text) + { return text.GenerateHash(); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installer.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installer.aspx.cs index bdcbfaa775..a9bf7b5e43 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installer.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installer.aspx.cs @@ -134,7 +134,7 @@ namespace umbraco.presentation.developer.packages protected void fetchProtectedPackage(object sender, EventArgs e) { //we auth against the webservice. This key will be used to fetch the protected package. - string memberGuid = _repo.Webservice.authenticate(tb_email.Text, library.md5(tb_password.Text)); + string memberGuid = _repo.Webservice.authenticate(tb_email.Text, library.CreateHash(tb_password.Text)); //if we auth correctly and get a valid key back, we will fetch the file from the repo webservice. if (string.IsNullOrEmpty(memberGuid) == false) diff --git a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs index cddf6bc5dd..f3f488ac1b 100644 --- a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs +++ b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Text; using System.Threading; @@ -26,6 +27,19 @@ namespace umbraco.MacroEngines return "~/" + physicalPath; } + [Obsolete("Please use the GetHash method instead. This may be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] + public string GetMd5(string text) + { + return text.ToMd5(); + } + + /// + /// Generates a hash based on the text string passed in. This method will detect the + /// security requirements (is FIPS enabled) and return an appropriate hash. + /// + /// String value to hash + /// The hash of the text string public string GetHash(string text) { return text.GenerateHash(); } From 9a515de43fb1a95569fec707dae39dedceb22065 Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Tue, 16 May 2017 09:12:50 -0700 Subject: [PATCH 04/12] Updated Examine Nuget to latest version 1.8.3 --- src/Umbraco.Tests/Umbraco.Tests.csproj | 5 +++-- src/Umbraco.Tests/packages.config | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 5 +++-- src/Umbraco.Web.UI/packages.config | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 4 ++-- src/Umbraco.Web/packages.config | 2 +- src/UmbracoExamine/UmbracoExamine.csproj | 4 ++-- src/UmbracoExamine/packages.config | 2 +- src/umbraco.MacroEngines/packages.config | 2 +- src/umbraco.MacroEngines/umbraco.MacroEngines.csproj | 4 ++-- 10 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index eb57d210fc..067109d8bf 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -61,8 +61,9 @@ ..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - ..\packages\Examine.0.1.82\lib\net45\Examine.dll + + ..\packages\Examine.0.1.83\lib\net45\Examine.dll + True ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config index a9cbce1aad..d1ffb2420e 100644 --- a/src/Umbraco.Tests/packages.config +++ b/src/Umbraco.Tests/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index fc7827c591..288da6b3d2 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -127,8 +127,9 @@ ..\packages\dotless.1.5.2\lib\dotless.Core.dll - - ..\packages\Examine.0.1.82\lib\net45\Examine.dll + + ..\packages\Examine.0.1.83\lib\net45\Examine.dll + True False diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 555740eda3..8b22708406 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -4,7 +4,7 @@ - + diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index d3e31fa366..bf63513085 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -116,8 +116,8 @@ ..\packages\dotless.1.5.2\lib\dotless.Core.dll - - ..\packages\Examine.0.1.82\lib\net45\Examine.dll + + ..\packages\Examine.0.1.83\lib\net45\Examine.dll True diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index b7625770a3..daef6ee7fd 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/UmbracoExamine/UmbracoExamine.csproj b/src/UmbracoExamine/UmbracoExamine.csproj index 19abcf9313..9a3299fb7e 100644 --- a/src/UmbracoExamine/UmbracoExamine.csproj +++ b/src/UmbracoExamine/UmbracoExamine.csproj @@ -82,8 +82,8 @@ ..\Solution Items\TheFARM-Public.snk - - ..\packages\Examine.0.1.82\lib\net45\Examine.dll + + ..\packages\Examine.0.1.83\lib\net45\Examine.dll True diff --git a/src/UmbracoExamine/packages.config b/src/UmbracoExamine/packages.config index 17c77f7284..10206f1d14 100644 --- a/src/UmbracoExamine/packages.config +++ b/src/UmbracoExamine/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/umbraco.MacroEngines/packages.config b/src/umbraco.MacroEngines/packages.config index e125024a28..7479987df2 100644 --- a/src/umbraco.MacroEngines/packages.config +++ b/src/umbraco.MacroEngines/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj index 33cfdacd2f..07b70e24a4 100644 --- a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj +++ b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj @@ -45,8 +45,8 @@ false - - ..\packages\Examine.0.1.82\lib\net45\Examine.dll + + ..\packages\Examine.0.1.83\lib\net45\Examine.dll True From 2334596bf3df83183b34dd64af58bbb9d9cc142c Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Tue, 16 May 2017 11:06:00 -0700 Subject: [PATCH 05/12] Update Unit Tests to check for the correct version of Examine --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index 47e10bbcef..ccf6e87812 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -34,7 +34,7 @@ - + From a50256d3819a3048432f3b4085ee0653406d5226 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 1 Jun 2017 17:58:22 +0200 Subject: [PATCH 06/12] Enable trying to convert urls to ascii --- .../UmbracoSettings/IRequestHandlerSection.cs | 2 ++ .../UmbracoSettings/RequestHandlerElement.cs | 7 +++- .../UmbracoSettings/UrlReplacingElement.cs | 6 ++-- src/Umbraco.Core/Strings/CleanStringType.cs | 6 +++- .../Strings/DefaultShortStringHelper.cs | 25 +++++++++++--- .../Strings/Utf8ToAsciiConverter.cs | 22 ++++++++----- .../Strings/DefaultShortStringHelperTests.cs | 33 +++++++++++++++++-- 7 files changed, 80 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs index 2d78e68bf5..a8b8d17ad9 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs @@ -12,6 +12,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool ConvertUrlsToAscii { get; } + bool TryConvertUrlsToAscii { get; } + IEnumerable CharCollection { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs index 779d33c8b8..c040c83708 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs @@ -111,7 +111,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool IRequestHandlerSection.ConvertUrlsToAscii { - get { return UrlReplacing.ConvertUrlsToAscii; } + get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true"); } + } + + bool IRequestHandlerSection.TryConvertUrlsToAscii + { + get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try"); } } IEnumerable IRequestHandlerSection.CharCollection diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs index a378a27dcd..887528fb4a 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs @@ -11,10 +11,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return (bool) base["removeDoubleDashes"]; } } - [ConfigurationProperty("toAscii", DefaultValue = false)] - internal bool ConvertUrlsToAscii + [ConfigurationProperty("toAscii", DefaultValue = "false")] + internal string ConvertUrlsToAscii { - get { return (bool)base["toAscii"]; } + get { return (string) base["toAscii"]; } } [ConfigurationCollection(typeof(CharCollection), AddItemName = "char")] diff --git a/src/Umbraco.Core/Strings/CleanStringType.cs b/src/Umbraco.Core/Strings/CleanStringType.cs index 0e0a7c9908..c8c99be869 100644 --- a/src/Umbraco.Core/Strings/CleanStringType.cs +++ b/src/Umbraco.Core/Strings/CleanStringType.cs @@ -68,7 +68,7 @@ namespace Umbraco.Core.Strings /// /// Flag mask for encoding. /// - CodeMask = Unicode | Utf8 | Ascii, + CodeMask = Unicode | Utf8 | Ascii | TryAscii, /// /// Unicode encoding. @@ -86,6 +86,10 @@ namespace Umbraco.Core.Strings /// Ascii = 0x0400, + /// + /// Ascii encoding, if possible. + /// + TryAscii = 0x0800, // role values diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index 96b8187e22..40a0c71778 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -152,12 +152,18 @@ namespace Umbraco.Core.Strings /// The short string helper. public DefaultShortStringHelper WithDefaultConfig() { + var urlSegmentConvertTo = CleanStringType.Utf8; + if (_umbracoSettings.RequestHandler.ConvertUrlsToAscii) + urlSegmentConvertTo = CleanStringType.Ascii; + if (_umbracoSettings.RequestHandler.TryConvertUrlsToAscii) + urlSegmentConvertTo = CleanStringType.TryAscii; + return WithConfig(CleanStringType.UrlSegment, new Config { PreFilter = ApplyUrlReplaceCharacters, PostFilter = x => CutMaxLength(x, 240), IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore - StringType = (_umbracoSettings.RequestHandler.ConvertUrlsToAscii ? CleanStringType.Ascii : CleanStringType.Utf8) | CleanStringType.LowerCase, + StringType = urlSegmentConvertTo | CleanStringType.LowerCase, BreakTermsOnUpper = false, Separator = '-' }).WithConfig(CleanStringType.FileName, new Config @@ -542,9 +548,20 @@ function validateSafeAlias(input, value, immediate, callback) {{ // recode var codeType = stringType & CleanStringType.CodeMask; - text = codeType == CleanStringType.Ascii - ? Utf8ToAsciiConverter.ToAsciiString(text) - : RemoveSurrogatePairs(text); + switch (codeType) + { + case CleanStringType.Ascii: + text = Utf8ToAsciiConverter.ToAsciiString(text); + break; + case CleanStringType.TryAscii: + const char ESC = (char) 27; + var ctext = Utf8ToAsciiConverter.ToAsciiString(text, ESC); + if (ctext.Contains(ESC) == false) text = ctext; + break; + default: + text = RemoveSurrogatePairs(text); + break; + } // clean text = CleanCodeString(text, stringType, separator.Value, culture, config); diff --git a/src/Umbraco.Core/Strings/Utf8ToAsciiConverter.cs b/src/Umbraco.Core/Strings/Utf8ToAsciiConverter.cs index e08defdedd..7a25f18c11 100644 --- a/src/Umbraco.Core/Strings/Utf8ToAsciiConverter.cs +++ b/src/Umbraco.Core/Strings/Utf8ToAsciiConverter.cs @@ -17,8 +17,9 @@ namespace Umbraco.Core.Strings /// Converts an Utf8 string into an Ascii string. /// /// The text to convert. + /// The character to used to replace characters that cannot properly be converted. /// The converted text. - public static string ToAsciiString(string text) + public static string ToAsciiString(string text, char fail = '?') { var input = text.ToCharArray(); @@ -26,7 +27,7 @@ namespace Umbraco.Core.Strings // but... we should be filtering short strings only... var output = new char[input.Length * 3]; // *3 because of things such as OE - var len = ToAscii(input, output); + var len = ToAscii(input, output, fail); return new string(output, 0, len); //var output = new StringBuilder(input.Length + 16); // default is 16, start with at least input length + little extra @@ -38,8 +39,9 @@ namespace Umbraco.Core.Strings /// Converts an Utf8 string into an array of Ascii characters. /// /// The text to convert. + /// The character to used to replace characters that cannot properly be converted. /// The converted text. - public static char[] ToAsciiCharArray(string text) + public static char[] ToAsciiCharArray(string text, char fail = '?') { var input = text.ToCharArray(); @@ -47,7 +49,7 @@ namespace Umbraco.Core.Strings // but... we should be filtering short strings only... var output = new char[input.Length * 3]; // *3 because of things such as OE - var len = ToAscii(input, output); + var len = ToAscii(input, output, fail); var array = new char[len]; Array.Copy(output, array, len); return array; @@ -64,10 +66,11 @@ namespace Umbraco.Core.Strings /// /// The input array. /// The output array. + /// The character to used to replace characters that cannot properly be converted. /// The number of characters in the output array. /// The caller must ensure that the output array is big enough. /// The output array is not big enough. - private static int ToAscii(char[] input, char[] output) + private static int ToAscii(char[] input, char[] output, char fail = '?') { var opos = 0; @@ -75,10 +78,10 @@ namespace Umbraco.Core.Strings if (char.IsSurrogate(input[ipos])) // ignore high surrogate { ipos++; // and skip low surrogate - output[opos++] = '?'; + output[opos++] = fail; } else - ToAscii(input, ipos, output, ref opos); + ToAscii(input, ipos, output, ref opos, fail); return opos; } @@ -109,12 +112,13 @@ namespace Umbraco.Core.Strings /// The input position. /// The output array. /// The output position. + /// The character to used to replace characters that cannot properly be converted. /// /// Adapted from various sources on the 'net including Lucene.Net.Analysis.ASCIIFoldingFilter. /// Input should contain Utf8 characters exclusively and NOT Unicode. /// Removes controls, normalizes whitespaces, replaces symbols by '?'. /// - private static void ToAscii(char[] input, int ipos, char[] output, ref int opos) + private static void ToAscii(char[] input, int ipos, char[] output, ref int opos, char fail = '?') { var c = input[ipos]; @@ -3583,7 +3587,7 @@ namespace Umbraco.Core.Strings // output[opos++] = c; // strict ASCII - output[opos++] = '?'; + output[opos++] = fail; break; } diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 58b0451995..b528e81131 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -16,7 +16,7 @@ using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Strings { [TestFixture] - public class DefaultShortStringHelperTests + public class DefaultShortStringHelperTests { private DefaultShortStringHelper _helper; @@ -145,6 +145,33 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("aeoa-and-aeoa-and-and-and-grosser-bbddzhzh-page", output); } + [Test] + public void U4_4056_TryAscii() + { + var settings = SettingsForTests.GenerateMockSettings(); + var contentMock = Mock.Get(settings.RequestHandler); + contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); + contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + SettingsForTests.ConfigureSettings(settings); + + const string input1 = "ÆØÅ and æøå and 中文测试 and אודות האתר and größer БбДдЖж page"; + const string input2 = "ÆØÅ and æøå and größer БбДдЖж page"; + + var helper = new DefaultShortStringHelper(settings).WithDefaultConfig(); // unicode + Assert.AreEqual("æøå-and-æøå-and-中文测试-and-אודות-האתר-and-größer-ббдджж-page", helper.CleanStringForUrlSegment(input1)); + Assert.AreEqual("æøå-and-æøå-and-größer-ббдджж-page", helper.CleanStringForUrlSegment(input2)); + + helper = new DefaultShortStringHelper(SettingsForTests.GetDefault()) + .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelper.Config + { + IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', + StringType = CleanStringType.LowerCase | CleanStringType.TryAscii, // try ascii + Separator = '-' + }); + Assert.AreEqual("æøå-and-æøå-and-中文测试-and-אודות-האתר-and-größer-ббдджж-page", helper.CleanStringForUrlSegment(input1)); + Assert.AreEqual("aeoa-and-aeoa-and-grosser-bbddzhzh-page", helper.CleanStringForUrlSegment(input2)); + } + [Test] public void CleanStringUnderscoreInTerm() { @@ -339,7 +366,7 @@ namespace Umbraco.Tests.Strings Separator = '*' }); Assert.AreEqual("house*2", helper.CleanString("house (2)", CleanStringType.Alias)); - + // FIXME but for a filename we want to keep them! // FIXME and what about a url? } @@ -574,7 +601,7 @@ namespace Umbraco.Tests.Strings { var output = _helper.SplitPascalCasing(input, ' '); Assert.AreEqual(expected, output); - + output = _helper.SplitPascalCasing(input, '*'); expected = expected.Replace(' ', '*'); Assert.AreEqual(expected, output); From 92a507bc87e3d3fdcbd2875309d9d15deb5aaf5a Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 5 Jun 2017 16:02:04 +0200 Subject: [PATCH 07/12] New CG year --- src/Umbraco.Web.UI.Client/src/installer/installer.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js index 3ba655d934..b2693f344e 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js +++ b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js @@ -31,7 +31,7 @@ angular.module("umbraco.install").factory('installerService', function($rootScop "At least 4 people have the Umbraco logo tattooed on them", "'Umbraco' is the danish name for an allen key", "Umbraco has been around since 2005, that's a looong time in IT", - "More than 550 people from all over the world meet each year in Denmark in June for our annual conference CodeGarden", + "More than 550 people from all over the world meet each year in Denmark in June for our annual conference CodeGarden", "While you are installing Umbraco someone else on the other side of the planet is probably doing it too", "You can extend Umbraco without modifying the source code using either JavaScript or C#", "Umbraco was installed in more than 165 countries in 2015" From 2191d338446005bdca1a2f1c37c755127ae2853d Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 5 Jun 2017 16:33:47 +0200 Subject: [PATCH 08/12] Bumps version --- build/UmbracoVersion.txt | 2 +- src/SolutionInfo.cs | 4 ++-- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/UmbracoVersion.txt b/build/UmbracoVersion.txt index e591b5dfcb..c12ac783cc 100644 --- a/build/UmbracoVersion.txt +++ b/build/UmbracoVersion.txt @@ -1,2 +1,2 @@ # Usage: on line 2 put the release version, on line 3 put the version comment (example: beta) -7.6.3 \ No newline at end of file +7.6.4 \ No newline at end of file diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index d7e4c9a204..fe3be21eb7 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -11,5 +11,5 @@ using System.Resources; [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("7.6.3")] -[assembly: AssemblyInformationalVersion("7.6.3")] \ No newline at end of file +[assembly: AssemblyFileVersion("7.6.4")] +[assembly: AssemblyInformationalVersion("7.6.4")] \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index eba9c4f1f2..bd971b6d86 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -2376,9 +2376,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" True True - 7630 + 7640 / - http://localhost:7630 + http://localhost:7640 False False From 5eb330b7d7d106f21545cca1d39d4954cf71651b Mon Sep 17 00:00:00 2001 From: Jeavon Leopold Date: Mon, 5 Jun 2017 17:32:05 +0200 Subject: [PATCH 09/12] Add GetAbsoluteMediaUrl method to UrlHelper for the Open Graph starter kit lesson --- src/Umbraco.Web/UrlHelperRenderExtensions.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Umbraco.Web/UrlHelperRenderExtensions.cs b/src/Umbraco.Web/UrlHelperRenderExtensions.cs index 614c815f79..a451503803 100644 --- a/src/Umbraco.Web/UrlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/UrlHelperRenderExtensions.cs @@ -343,5 +343,24 @@ namespace Umbraco.Web { return url.SurfaceAction(action, typeof (T), additionalRouteVals); } + + /// + /// Generates a Absolute Media Item URL based on the current context + /// + /// + /// + /// + public static string GetAbsoluteMediaUrl(this UrlHelper urlHelper, IPublishedContent mediaItem) + { + if (urlHelper == null) throw new ArgumentNullException("urlHelper"); + if (mediaItem == null) throw new ArgumentNullException("mediaItem"); + + if (urlHelper.RequestContext.HttpContext.Request.Url != null) + { + var requestUrl = urlHelper.RequestContext.HttpContext.Request.Url.GetLeftPart(UriPartial.Authority); + return string.Format("{0}{1}", requestUrl, mediaItem.Url); + } + return null; + } } } \ No newline at end of file From 160518e97720b6dab0a12c82fb5f2c6f14e31cac Mon Sep 17 00:00:00 2001 From: Claus Date: Mon, 12 Jun 2017 12:12:14 +0200 Subject: [PATCH 10/12] adding guids to backoffice. --- .../editor/umbeditorheader.directive.js | 3 +- src/Umbraco.Web.UI.Client/src/less/panel.less | 6 ++++ .../components/editor/umb-editor-header.html | 4 ++- .../src/views/datatypes/edit.html | 1 + .../src/views/documenttypes/edit.html | 1 + .../src/views/mediatypes/edit.html | 1 + .../src/views/templates/edit.html | 1 + .../umbraco/developer/Macros/editMacro.aspx | 3 ++ .../Models/ContentEditing/TemplateDisplay.cs | 7 ++--- .../Models/Mapping/TemplateModelMapper.cs | 1 - .../developer/Macros/editMacro.aspx.cs | 28 +++++++++++++------ 11 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js index 4d9222fa45..8ef43df47b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js @@ -255,7 +255,8 @@ Use this directive to construct a header inside the main editor window. description: "=", hideDescription: "@", descriptionLocked: "@", - navigation: "=" + navigation: "=", + key: "=" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index 6bc2a2b2de..0446d9752b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -489,6 +489,12 @@ input.umb-panel-header-description { line-height: 25px; } +.umb-panel-header-key { + font-size: 10px; + margin-left: 8px; + color: #adadad; +} + .umb-editor-drawer-content { display: flex; align-items: center; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html index f55b587c04..9a84a1a645 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html @@ -47,7 +47,9 @@ ng-if="!hideDescription && !descriptionLocked" ng-model="$parent.description" /> -
{{ description }}
+
{{ description }}
+ +
{{ key }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/datatypes/edit.html index fc53982b90..9f52357c31 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/edit.html @@ -12,6 +12,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.html index 5bde09f8e0..f0d3a8fbf6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.html @@ -9,6 +9,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html index ec8ca3e9b4..2d59b644d0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html @@ -13,6 +13,7 @@ + + + diff --git a/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs index 91c1aefdb0..ffa4e4e100 100644 --- a/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs @@ -1,11 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; using System.Runtime.Serialization; -using System.Text; -using System.Threading.Tasks; -using Umbraco.Core.Models.Validation; namespace Umbraco.Web.Models.ContentEditing { @@ -24,6 +20,9 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "alias")] public string Alias { get; set; } + [DataMember(Name = "key")] + public Guid Key { get; set; } + [DataMember(Name = "content")] public string Content { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/TemplateModelMapper.cs b/src/Umbraco.Web/Models/Mapping/TemplateModelMapper.cs index 19677fccc8..6111941084 100644 --- a/src/Umbraco.Web/Models/Mapping/TemplateModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/TemplateModelMapper.cs @@ -15,7 +15,6 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() .ForMember(x => x.DeletedDate, exp => exp.Ignore()) - .ForMember(x => x.Key, exp => exp.Ignore()) .ForMember(x => x.Path, exp => exp.Ignore()) .ForMember(x => x.CreateDate, exp => exp.Ignore()) .ForMember(x => x.UpdateDate, exp => exp.Ignore()) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs index b40515578b..73800ca117 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs @@ -88,6 +88,7 @@ namespace umbraco.cms.presentation.developer { macroName.Text = macro.Name; macroAlias.Text = macro.Alias; + macroKey.Text = macro.Key.ToString(); macroXslt.Text = macro.XsltPath; macroPython.Text = macro.ScriptPath; cachePeriod.Text = macro.CacheDuration.ToInvariantString(); @@ -209,7 +210,7 @@ namespace umbraco.cms.presentation.developer } protected IEnumerable GetMacroParameterEditors() - { + { // we need to show the depracated ones for backwards compatibility return ParameterEditorResolver.Current.GetParameterEditors(true); } @@ -433,14 +434,23 @@ namespace umbraco.cms.presentation.developer /// protected global::System.Web.UI.WebControls.TextBox macroAlias; - /// - /// Pane1_2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane Pane1_2; + /// + /// macroAlias control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label macroKey; + + /// + /// Pane1_2 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.Pane Pane1_2; /// /// macroXslt control. From e559a6d48516fd00abe027e80b06242367b0ea23 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 12 Jun 2017 14:55:12 +0200 Subject: [PATCH 11/12] add key as hover on name --- src/Umbraco.Web.UI.Client/src/less/panel.less | 6 ----- .../components/editor/umb-editor-header.html | 23 ++++++++++--------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index 0446d9752b..6bc2a2b2de 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -489,12 +489,6 @@ input.umb-panel-header-description { line-height: 25px; } -.umb-panel-header-key { - font-size: 10px; - margin-left: 8px; - color: #adadad; -} - .umb-editor-drawer-content { display: flex; align-items: center; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html index 9a84a1a645..fdc1ddf0f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html @@ -17,6 +17,7 @@ -
{{ name }}
+
{{ name }}
+ - + + +
{{ description }}
-
{{ description }}
- -
{{ key }}
From 917a2b78dde53442104703c0c4a6ea75608a21d5 Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Mon, 12 Jun 2017 13:44:42 -0700 Subject: [PATCH 12/12] Added RFC 4122 compliant GUID support to the ToGuid() method on StrringExtensions.cs. Verified the SHA1 hash works with the ToGuid() method via unit tests. --- src/Umbraco.Core/StringExtensions.cs | 79 +++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index f540305325..dba7f2cfee 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -1470,7 +1470,84 @@ namespace Umbraco.Core /// internal static Guid ToGuid(this string text) { - return new Guid(text.GenerateHash()); + return CreateGuidFromHash(UrlNamespace, + text, + CryptoConfig.AllowOnlyFipsAlgorithms + ? 5 // SHA1 + : 3); // MD5 + } + + /// + /// The namespace for URLs (from RFC 4122, Appendix C). + /// + /// See RFC 4122 + /// + internal static readonly Guid UrlNamespace = new Guid("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); + + /// + /// Creates a name-based UUID using the algorithm from RFC 4122 §4.3. + /// + /// See GuidUtility.cs for original implementation. + /// + /// The ID of the namespace. + /// The name (within that namespace). + /// The version number of the UUID to create; this value must be either + /// 3 (for MD5 hashing) or 5 (for SHA-1 hashing). + /// A UUID derived from the namespace and name. + /// See Generating a deterministic GUID. + internal static Guid CreateGuidFromHash(Guid namespaceId, string name, int version) + { + if (name == null) + throw new ArgumentNullException("name"); + if (version != 3 && version != 5) + throw new ArgumentOutOfRangeException("version", "version must be either 3 or 5."); + + // convert the name to a sequence of octets (as defined by the standard or conventions of its namespace) (step 3) + // ASSUME: UTF-8 encoding is always appropriate + byte[] nameBytes = Encoding.UTF8.GetBytes(name); + + // convert the namespace UUID to network order (step 3) + byte[] namespaceBytes = namespaceId.ToByteArray(); + SwapByteOrder(namespaceBytes); + + // comput the hash of the name space ID concatenated with the name (step 4) + byte[] hash; + using (HashAlgorithm algorithm = version == 3 ? (HashAlgorithm)MD5.Create() : SHA1.Create()) + { + algorithm.TransformBlock(namespaceBytes, 0, namespaceBytes.Length, null, 0); + algorithm.TransformFinalBlock(nameBytes, 0, nameBytes.Length); + hash = algorithm.Hash; + } + + // most bytes from the hash are copied straight to the bytes of the new GUID (steps 5-7, 9, 11-12) + byte[] newGuid = new byte[16]; + Array.Copy(hash, 0, newGuid, 0, 16); + + // set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the appropriate 4-bit version number from Section 4.1.3 (step 8) + newGuid[6] = (byte)((newGuid[6] & 0x0F) | (version << 4)); + + // set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively (step 10) + newGuid[8] = (byte)((newGuid[8] & 0x3F) | 0x80); + + // convert the resulting UUID to local byte order (step 13) + SwapByteOrder(newGuid); + return new Guid(newGuid); + } + + // Converts a GUID (expressed as a byte array) to/from network order (MSB-first). + internal static void SwapByteOrder(byte[] guid) + { + SwapBytes(guid, 0, 3); + SwapBytes(guid, 1, 2); + SwapBytes(guid, 4, 5); + SwapBytes(guid, 6, 7); + } + + private static void SwapBytes(byte[] guid, int left, int right) + { + byte temp = guid[left]; + guid[left] = guid[right]; + guid[right] = temp; } } }