Skip to content

Commit

Permalink
Fixed issue with Paths-integers being converted using local culture. (u…
Browse files Browse the repository at this point in the history
…mbraco#11180)

* Fixed issue with Paths-integers being converted using local culture.

* Align with the old implementation

* Use int.TryParse insteaad of TryConvertTo when we do not want culture specific parsing

* More fixes for cultures and fixed wrong test. Users should be part of all groups to have access

* Fix casing for requested file

* Force tests to not use NLS

* try force tests to not use NLS

* try force tests to not use NLS

* Force tests on windows to run ICU

* More fixes for invariant int parsing

* Change key on actions/emptyRecycleBin, so the casing aligns with the view file, that is named emptyrecyclebin.html

* Fixed casing issue

* use Attempt to align with other code
  • Loading branch information
bergmania authored Sep 24, 2021
1 parent 9367572 commit 452097d
Show file tree
Hide file tree
Showing 49 changed files with 173 additions and 261 deletions.
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ static StringExtensions()
public static int[] GetIdsFromPathReversed(this string path)
{
var nodeIds = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.TryConvertTo<int>())
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var output) ? Attempt<int>.Succeed(output) : Attempt<int>.Fail())
.Where(x => x.Success)
.Select(x => x.Result)
.Select(x=>x.Result)
.Reverse()
.ToArray();
return nodeIds;
Expand Down
4 changes: 4 additions & 0 deletions src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ private IEnumerable<EditorNavigation> CreateUserEditorNavigation()

private static int GetIntId(object id)
{
if (id is string strId && int.TryParse(strId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var asInt))
{
return asInt;
}
var result = id.TryConvertTo<int>();
if (result.Success == false)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Umbraco.Core/Models/UserExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,14 @@ private static bool StartsWithPath(string test, string path)

private static string GetBinPath(UmbracoObjectTypes objectType)
{
var binPath = Constants.System.Root + ",";
var binPath = Constants.System.RootString + ",";
switch (objectType)
{
case UmbracoObjectTypes.Document:
binPath += Constants.System.RecycleBinContent;
binPath += Constants.System.RecycleBinContentString;
break;
case UmbracoObjectTypes.Media:
binPath += Constants.System.RecycleBinMedia;
binPath += Constants.System.RecycleBinMediaString;
break;
default:
throw new ArgumentOutOfRangeException(nameof(objectType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,20 @@ public override object ConvertSourceToIntermediate(IPublishedElement owner, IPub
{
if (source == null) return null;


if(source is not string)
{
var attemptConvertInt = source.TryConvertTo<int>();
if (attemptConvertInt.Success)
return attemptConvertInt.Result;
}
//Don't attempt to convert to int for UDI
if(!(source is string) || source is string strSource && !string.IsNullOrWhiteSpace(strSource) && !strSource.StartsWith("umb"))
if( source is string strSource
&& !string.IsNullOrWhiteSpace(strSource)
&& !strSource.StartsWith("umb")
&& int.TryParse(strSource, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue))
{
var attemptConvertInt = source.TryConvertTo<int>();
if (attemptConvertInt.Success)
return attemptConvertInt.Result;
return intValue;
}

var attemptConvertUdi = source.TryConvertTo<Udi>();
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Security/ContentPermissions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,11 @@ public static bool HasPathAccess(string path, int[] startNodeIds, int recycleBin

// only users with root access have access to the recycle bin,
// if the above check didn't pass then access is denied
if (formattedPath.Contains(string.Concat(",", recycleBinId, ",")))
if (formattedPath.Contains(string.Concat(",", recycleBinId.ToString(CultureInfo.InvariantCulture), ",")))
return false;

// check for a start node in the path
return startNodeIds.Any(x => formattedPath.Contains(string.Concat(",", x, ",")));
return startNodeIds.Any(x => formattedPath.Contains(string.Concat(",", x.ToString(CultureInfo.InvariantCulture), ",")));
}

public static bool IsInBranchOfStartNode(string path, int[] startNodeIds, string[] startNodePaths, out bool hasPathAccess)
Expand Down
5 changes: 3 additions & 2 deletions src/Umbraco.Core/Services/UserServiceExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.Membership;
Expand All @@ -12,9 +13,9 @@ public static class UserServiceExtensions
public static EntityPermission GetPermissions(this IUserService userService, IUser user, string path)
{
var ids = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.TryConvertTo<int>())
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? Attempt<int>.Succeed(value) : Attempt<int>.Fail())
.Where(x => x.Success)
.Select(x => x.Result)
.Select(x=>x.Result)
.ToArray();
if (ids.Length == 0) throw new InvalidOperationException("The path: " + path + " could not be parsed into an array of integers or the path was empty");

Expand Down
86 changes: 0 additions & 86 deletions src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,91 +382,5 @@ private void AppendPath(StringBuilder sb, string path, bool includeThisNode)
sb.Append(path);
sb.Append("\\,*");
}

// TODO: When/Where is this used?

/// <summary>
/// Returns a collection of entities for media based on search results
/// </summary>
/// <param name="results"></param>
/// <returns></returns>
private IEnumerable<SearchResultEntity> MemberFromSearchResults(IEnumerable<ISearchResult> results)
{
//add additional data
foreach (var result in results)
{
var m = _umbracoMapper.Map<SearchResultEntity>(result);

//if no icon could be mapped, it will be set to document, so change it to picture
if (m.Icon == Constants.Icons.DefaultIcon)
{
m.Icon = Constants.Icons.Member;
}

if (result.Values.ContainsKey("email") && result.Values["email"] != null)
{
m.AdditionalData["Email"] = result.Values["email"];
}
if (result.Values.ContainsKey(UmbracoExamineFieldNames.NodeKeyFieldName) && result.Values[UmbracoExamineFieldNames.NodeKeyFieldName] != null)
{
if (Guid.TryParse(result.Values[UmbracoExamineFieldNames.NodeKeyFieldName], out var key))
{
m.Key = key;
}
}

yield return m;
}
}

// TODO: When/Where is this used?

/// <summary>
/// Returns a collection of entities for media based on search results
/// </summary>
/// <param name="results"></param>
/// <returns></returns>
private IEnumerable<SearchResultEntity> MediaFromSearchResults(IEnumerable<ISearchResult> results)
=> _umbracoMapper.Map<IEnumerable<SearchResultEntity>>(results);

// TODO: When/Where is this used?

/// <summary>
/// Returns a collection of entities for content based on search results
/// </summary>
/// <param name="results"></param>
/// <returns></returns>
private IEnumerable<SearchResultEntity> ContentFromSearchResults(IEnumerable<ISearchResult> results, string culture = null)
{
var defaultLang = _languageService.GetDefaultLanguageIsoCode();
foreach (var result in results)
{
var entity = _umbracoMapper.Map<SearchResultEntity>(result, context =>
{
if (culture != null)
{
context.SetCulture(culture);
}
}
);

var intId = entity.Id.TryConvertTo<int>();
if (intId.Success)
{
//if it varies by culture, return the default language URL
if (result.Values.TryGetValue(UmbracoExamineFieldNames.VariesByCultureFieldName, out var varies) && varies == "y")
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result, culture: culture ?? defaultLang);
}
else
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result);
}
}

yield return entity;
}
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Examine;
using Umbraco.Cms.Core.Scoping;
Expand Down Expand Up @@ -30,7 +31,7 @@ public bool ValidatePath(string path, string category)
{
// we cannot return FAILED here because we need the value set to get into the indexer and then deal with it from there
// because we need to remove anything that doesn't pass by parent Id in the cases that umbraco data is moved to an illegal parent.
if (!path.Contains(string.Concat(",", ParentId.Value, ",")))
if (!path.Contains(string.Concat(",", ParentId.Value.ToString(CultureInfo.InvariantCulture), ",")))
return false;
}

Expand All @@ -39,7 +40,7 @@ public bool ValidatePath(string path, string category)

public bool ValidateRecycleBin(string path, string category)
{
var recycleBinId = category == IndexTypes.Content ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia;
var recycleBinId = category == IndexTypes.Content ? Constants.System.RecycleBinContentString : Constants.System.RecycleBinMediaString;

//check for recycle bin
if (PublishedValuesOnly)
Expand Down
8 changes: 4 additions & 4 deletions src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Examine;
using Umbraco.Cms.Core.Mapping;
Expand Down Expand Up @@ -162,17 +163,16 @@ private IEnumerable<SearchResultEntity> ContentFromSearchResults(IEnumerable<ISe
}
);

var intId = entity.Id.TryConvertTo<int>();
if (intId.Success)
if (int.TryParse(entity.Id.ToString(),NumberStyles.Integer, CultureInfo.InvariantCulture, out var intId))
{
//if it varies by culture, return the default language URL
if (result.Values.TryGetValue(UmbracoExamineFieldNames.VariesByCultureFieldName, out var varies) && varies == "y")
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result, culture: culture ?? defaultLang);
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId, culture: culture ?? defaultLang);
}
else
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result);
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Events;
Expand Down Expand Up @@ -946,11 +947,7 @@ public IEnumerable<EntityContainer> GetContainers(int[] containerIds)
public IEnumerable<EntityContainer> GetContainers(TItem item)
{
var ancestorIds = item.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x =>
{
var asInt = x.TryConvertTo<int>();
return asInt ? asInt.Result : int.MinValue;
})
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var asInt) ? asInt : int.MinValue)
.Where(x => x != int.MinValue && x != item.Id)
.ToArray();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,11 @@ private XElement SerializePropertyType(IPropertyType propertyType, IDataType def
private XElement SerializeContentBase(IContentBase contentBase, string urlValue, string nodeName, bool published)
{
var xml = new XElement(nodeName,
new XAttribute("id", contentBase.Id),
new XAttribute("id", contentBase.Id.ToInvariantString()),
new XAttribute("key", contentBase.Key),
new XAttribute("parentID", contentBase.Level > 1 ? contentBase.ParentId : -1),
new XAttribute("parentID", (contentBase.Level > 1 ? contentBase.ParentId : -1).ToInvariantString()),
new XAttribute("level", contentBase.Level),
new XAttribute("creatorID", contentBase.CreatorId),
new XAttribute("creatorID", contentBase.CreatorId.ToInvariantString()),
new XAttribute("sortOrder", contentBase.SortOrder),
new XAttribute("createDate", contentBase.CreateDate.ToString("s")),
new XAttribute("updateDate", contentBase.UpdateDate.ToString("s")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<IsPackable>true</IsPackable>
</PropertyGroup>

<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.6" />
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2" />
</ItemGroup>

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<DefineConstants>IS_WINDOWS</DefineConstants>
</PropertyGroup>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,49 +49,43 @@ public void ConvertToBoolTest()


[Test]
[TestCase("en-US")]
[TestCase(null)]
[TestCase("da-DK")]
[TestCase("tr-TR")]
public void ConvertToIntegerTest(string culture)
[TestCase("en-US", -1, ExpectedResult = -1)]
[TestCase("en-US", "-1", ExpectedResult = -1)]
[TestCase("en-US", "100", ExpectedResult = 100)]
[TestCase("en-US", "100.000", ExpectedResult = 100)]
[TestCase("en-US", "100,000", ExpectedResult = 100)]
[TestCase("en-US", "100.001", ExpectedResult = 100)]
[TestCase("en-US", 100, ExpectedResult = 100)]
[TestCase("en-US", 100.000, ExpectedResult = 100)]
[TestCase("en-US", 100.001, ExpectedResult = 100)]
[TestCase("sv-SE", -1, ExpectedResult = -1)]
[TestCase("sv-SE", "−1", ExpectedResult = -1)] // Note '−' vs '-'
[TestCase("sv-SE", "100", ExpectedResult = 100)]
[TestCase("sv-SE", "100.000", ExpectedResult = 100)]
[TestCase("sv-SE", "100,000", ExpectedResult = 100)]
[TestCase("sv-SE", "100.001", ExpectedResult = 100)]
[TestCase("sv-SE", 100, ExpectedResult = 100)]
[TestCase("sv-SE", 100.000, ExpectedResult = 100)]
[TestCase("sv-SE", 100.001, ExpectedResult = 100)]
[TestCase("da-DK", "-1", ExpectedResult = -1)]
[TestCase("da-DK", -1, ExpectedResult = -1)]
[TestCase("da-DK", "100", ExpectedResult = 100)]
[TestCase("da-DK", "100.000", ExpectedResult = 100)]
[TestCase("da-DK", "100,000", ExpectedResult = 100)]
[TestCase("da-DK", "100.001", ExpectedResult = 100)]
[TestCase("da-DK", 100, ExpectedResult = 100)]
[TestCase("da-DK", 100.000, ExpectedResult = 100)]
[TestCase("da-DK", 100.001, ExpectedResult = 100)]
public int ConvertToIntegerTest(string culture, object input)
{
if (culture is not null)
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(culture);
}
var conv = "-1".TryConvertTo<int>();
var conv = input.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(-1, conv.Result);

conv = "100".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = "100.000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = "100,000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

// oops
conv = "100.001".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = 100m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = 100.000m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

// oops
conv = 100.001m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
return conv.Result;
}

[Test]
Expand Down
Loading

0 comments on commit 452097d

Please sign in to comment.