diff --git a/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs b/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs index 57c69ee9aa..1e492013b7 100644 --- a/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs +++ b/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Security.Claims; using System.Security.Principal; @@ -293,7 +294,7 @@ namespace Umbraco.Extensions /// /// /// User ID as integer - public static int GetId(this ClaimsIdentity identity) => int.Parse(identity.FindFirstValue(ClaimTypes.NameIdentifier)); + public static int GetId(this ClaimsIdentity identity) => int.Parse(identity.FindFirstValue(ClaimTypes.NameIdentifier), CultureInfo.InvariantCulture); /// /// Get the real name belonging to the user from a ClaimsIdentity diff --git a/src/Umbraco.Core/Extensions/ObjectExtensions.cs b/src/Umbraco.Core/Extensions/ObjectExtensions.cs index db2d63b643..bdde330c8f 100644 --- a/src/Umbraco.Core/Extensions/ObjectExtensions.cs +++ b/src/Umbraco.Core/Extensions/ObjectExtensions.cs @@ -6,6 +6,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -94,8 +95,8 @@ namespace Umbraco.Extensions { // sure, null can be any object return Attempt.Succeed((T)input); - } - } + } + } // just try to cast try @@ -293,7 +294,7 @@ namespace Umbraco.Extensions { if (target == typeof(int)) { - if (int.TryParse(input, out var value)) + if (int.TryParse(input, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { return Attempt.Succeed(value); } @@ -301,26 +302,26 @@ namespace Umbraco.Extensions // Because decimal 100.01m will happily convert to integer 100, it // makes sense that string "100.01" *also* converts to integer 100. var input2 = NormalizeNumberDecimalSeparator(input); - return Attempt.If(decimal.TryParse(input2, out var value2), Convert.ToInt32(value2)); + return Attempt.If(decimal.TryParse(input2, NumberStyles.Number, CultureInfo.InvariantCulture, out var value2), Convert.ToInt32(value2, CultureInfo.InvariantCulture)); } if (target == typeof(long)) { - if (long.TryParse(input, out var value)) + if (long.TryParse(input, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { return Attempt.Succeed(value); } // Same as int var input2 = NormalizeNumberDecimalSeparator(input); - return Attempt.If(decimal.TryParse(input2, out var value2), Convert.ToInt64(value2)); + return Attempt.If(decimal.TryParse(input2, NumberStyles.Number, CultureInfo.InvariantCulture, out var value2), Convert.ToInt64(value2)); } // TODO: Should we do the decimal trick for short, byte, unsigned? if (target == typeof(bool)) { - if (bool.TryParse(input, out var value)) + if (bool.TryParse(input, out var value)) { return Attempt.Succeed(value); } @@ -333,15 +334,15 @@ namespace Umbraco.Extensions switch (Type.GetTypeCode(target)) { case TypeCode.Int16: - return Attempt.If(short.TryParse(input, out var value), value); + return Attempt.If(short.TryParse(input, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value), value); case TypeCode.Double: var input2 = NormalizeNumberDecimalSeparator(input); - return Attempt.If(double.TryParse(input2, out var valueD), valueD); + return Attempt.If(double.TryParse(input2, NumberStyles.Float, CultureInfo.InvariantCulture, out var valueD), valueD); case TypeCode.Single: var input3 = NormalizeNumberDecimalSeparator(input); - return Attempt.If(float.TryParse(input3, out var valueF), valueF); + return Attempt.If(float.TryParse(input3, NumberStyles.Float, CultureInfo.InvariantCulture, out var valueF), valueF); case TypeCode.Char: return Attempt.If(char.TryParse(input, out var valueC), valueC); @@ -350,16 +351,16 @@ namespace Umbraco.Extensions return Attempt.If(byte.TryParse(input, out var valueB), valueB); case TypeCode.SByte: - return Attempt.If(sbyte.TryParse(input, out var valueSb), valueSb); + return Attempt.If(sbyte.TryParse(input, NumberStyles.Integer, CultureInfo.InvariantCulture, out var valueSb), valueSb); case TypeCode.UInt32: - return Attempt.If(uint.TryParse(input, out var valueU), valueU); + return Attempt.If(uint.TryParse(input, NumberStyles.Integer, CultureInfo.InvariantCulture, out var valueU), valueU); case TypeCode.UInt16: - return Attempt.If(ushort.TryParse(input, out var valueUs), valueUs); + return Attempt.If(ushort.TryParse(input, NumberStyles.Integer, CultureInfo.InvariantCulture, out var valueUs), valueUs); case TypeCode.UInt64: - return Attempt.If(ulong.TryParse(input, out var valueUl), valueUl); + return Attempt.If(ulong.TryParse(input, NumberStyles.Integer, CultureInfo.InvariantCulture, out var valueUl), valueUl); } } else if (target == typeof(Guid)) @@ -368,7 +369,7 @@ namespace Umbraco.Extensions } else if (target == typeof(DateTime)) { - if (DateTime.TryParse(input, out var value)) + if (DateTime.TryParse(input, CultureInfo.InvariantCulture, DateTimeStyles.None, out var value)) { switch (value.Kind) { @@ -388,16 +389,16 @@ namespace Umbraco.Extensions } else if (target == typeof(DateTimeOffset)) { - return Attempt.If(DateTimeOffset.TryParse(input, out var value), value); + return Attempt.If(DateTimeOffset.TryParse(input, CultureInfo.InvariantCulture, DateTimeStyles.None,out var value), value); } else if (target == typeof(TimeSpan)) { - return Attempt.If(TimeSpan.TryParse(input, out var value), value); + return Attempt.If(TimeSpan.TryParse(input, CultureInfo.InvariantCulture, out var value), value); } else if (target == typeof(decimal)) { var input2 = NormalizeNumberDecimalSeparator(input); - return Attempt.If(decimal.TryParse(input2, out var value), value); + return Attempt.If(decimal.TryParse(input2, NumberStyles.Number, CultureInfo.InvariantCulture, out var value), value); } else if (input != null && target == typeof(Version)) { @@ -676,7 +677,7 @@ namespace Umbraco.Extensions [MethodImpl(MethodImplOptions.AggressiveInlining)] private static string NormalizeNumberDecimalSeparator(string s) { - var normalized = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator[0]; + var normalized = CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator[0]; return s.ReplaceMany(NumberDecimalSeparatorsToNormalize, normalized); } diff --git a/src/Umbraco.Core/Media/Exif/ExifBitConverter.cs b/src/Umbraco.Core/Media/Exif/ExifBitConverter.cs index 900c9b1b43..74465a6684 100644 --- a/src/Umbraco.Core/Media/Exif/ExifBitConverter.cs +++ b/src/Umbraco.Core/Media/Exif/ExifBitConverter.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; namespace Umbraco.Cms.Core.Media.Exif @@ -65,12 +66,12 @@ namespace Umbraco.Cms.Core.Media.Exif // yyyy:MM:dd HH:mm:ss // This is the expected format though some cameras // can use single digits. See Issue 21. - return new DateTime(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]), int.Parse(parts[4]), int.Parse(parts[5])); + return new DateTime(int.Parse(parts[0], CultureInfo.InvariantCulture), int.Parse(parts[1], CultureInfo.InvariantCulture), int.Parse(parts[2], CultureInfo.InvariantCulture), int.Parse(parts[3], CultureInfo.InvariantCulture), int.Parse(parts[4], CultureInfo.InvariantCulture), int.Parse(parts[5], CultureInfo.InvariantCulture)); } else if (!hastime && parts.Length == 3) { // yyyy:MM:dd - return new DateTime(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2])); + return new DateTime(int.Parse(parts[0], CultureInfo.InvariantCulture), int.Parse(parts[1], CultureInfo.InvariantCulture), int.Parse(parts[2], CultureInfo.InvariantCulture)); } else { diff --git a/src/Umbraco.Core/Media/Exif/MathEx.cs b/src/Umbraco.Core/Media/Exif/MathEx.cs index dfad9ae7de..7334643bb3 100644 --- a/src/Umbraco.Core/Media/Exif/MathEx.cs +++ b/src/Umbraco.Core/Media/Exif/MathEx.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; namespace Umbraco.Cms.Core.Media.Exif @@ -714,8 +715,8 @@ namespace Umbraco.Cms.Core.Media.Exif } else if (sa.Length == 2) { - numerator = int.Parse(sa[0]); - denominator = int.Parse(sa[1]); + numerator = int.Parse(sa[0], CultureInfo.InvariantCulture); + denominator = int.Parse(sa[1], CultureInfo.InvariantCulture); } else throw new FormatException("The input string must be formatted as n/d where n and d are integers"); @@ -1342,8 +1343,8 @@ namespace Umbraco.Cms.Core.Media.Exif } else if (sa.Length == 2) { - numerator = uint.Parse(sa[0]); - denominator = uint.Parse(sa[1]); + numerator = uint.Parse(sa[0], CultureInfo.InvariantCulture); + denominator = uint.Parse(sa[1], CultureInfo.InvariantCulture); } else throw new FormatException("The input string must be formatted as n/d where n and d are integers"); diff --git a/src/Umbraco.Core/Media/Exif/SvgFile.cs b/src/Umbraco.Core/Media/Exif/SvgFile.cs index 00516eecb8..b83aebe1fb 100644 --- a/src/Umbraco.Core/Media/Exif/SvgFile.cs +++ b/src/Umbraco.Core/Media/Exif/SvgFile.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Globalization; +using System.IO; using System.Linq; using System.Xml.Linq; @@ -16,9 +17,9 @@ namespace Umbraco.Cms.Core.Media.Exif var height = document.Root?.Attributes().Where(x => x.Name == "height").Select(x => x.Value).FirstOrDefault(); Properties.Add(new ExifSInt(ExifTag.PixelYDimension, - height == null ? Constants.Conventions.Media.DefaultSize : int.Parse(height))); + height == null ? Constants.Conventions.Media.DefaultSize : int.Parse(height, CultureInfo.InvariantCulture))); Properties.Add(new ExifSInt(ExifTag.PixelXDimension, - width == null ? Constants.Conventions.Media.DefaultSize : int.Parse(width))); + width == null ? Constants.Conventions.Media.DefaultSize : int.Parse(width, CultureInfo.InvariantCulture))); Format = ImageFileFormat.SVG; } diff --git a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs index 7449a6f778..d3269c2c0b 100644 --- a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -601,7 +602,7 @@ namespace Umbraco.Cms.Core.Models.Mapping return Enumerable.Empty(); var aliases = new List(); - var ancestorIds = parent.Path.Split(Constants.CharArrays.Comma).Select(int.Parse); + var ancestorIds = parent.Path.Split(Constants.CharArrays.Comma).Select(s => int.Parse(s, CultureInfo.InvariantCulture)); // loop through all content types and return ordered aliases of ancestors var allContentTypes = _contentTypeService.GetAll().ToArray(); foreach (var ancestorId in ancestorIds) diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs index 4e5d854250..16248854e5 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; @@ -56,7 +57,7 @@ namespace Umbraco.Cms.Core.Routing var path = pos == 0 ? route : route.Substring(pos); var domainUri = pos == 0 ? null - : DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, int.Parse(route.Substring(0, pos)), current, culture); + : DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture), current, culture); // assemble the URL from domainUri (maybe null) and path var url = AssembleUrl(domainUri, path, current, mode).ToString(); diff --git a/src/Umbraco.Core/Routing/DomainUtilities.cs b/src/Umbraco.Core/Routing/DomainUtilities.cs index 035e57c43a..2e36e8c0ef 100644 --- a/src/Umbraco.Core/Routing/DomainUtilities.cs +++ b/src/Umbraco.Core/Routing/DomainUtilities.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Web; @@ -47,7 +48,7 @@ namespace Umbraco.Cms.Core.Routing var pos = route.IndexOf('/'); var domain = pos == 0 ? null - : DomainForNode(umbracoContext.Domains, siteDomainMapper, int.Parse(route.Substring(0, pos)), current); + : DomainForNode(umbracoContext.Domains, siteDomainMapper, int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture), current); var rootContentId = domain?.ContentId ?? -1; var wcDomain = FindWildcardDomainInPath(umbracoContext.Domains.GetAll(true), contentPath, rootContentId); @@ -329,7 +330,7 @@ namespace Umbraco.Cms.Core.Routing return path.Split(Constants.CharArrays.Comma) .Reverse() - .Select(int.Parse) + .Select(s => int.Parse(s, CultureInfo.InvariantCulture)) .TakeWhile(id => id != stopNodeId) .Select(id => domains.FirstOrDefault(d => d.ContentId == id && d.IsWildcard == false)) .SkipWhile(domain => domain == null) @@ -350,7 +351,7 @@ namespace Umbraco.Cms.Core.Routing return path.Split(Constants.CharArrays.Comma) .Reverse() - .Select(int.Parse) + .Select(s => int.Parse(s, CultureInfo.InvariantCulture)) .TakeWhile(id => id != stopNodeId) .Select(id => domains.FirstOrDefault(d => d.ContentId == id && d.IsWildcard)) .FirstOrDefault(domain => domain != null); diff --git a/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs b/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs index e92aa8e147..661d40be0c 100644 --- a/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs +++ b/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; namespace Umbraco.Cms.Core.Xml @@ -51,7 +52,7 @@ namespace Umbraco.Cms.Core.Xml int idAsInt; if (int.TryParse(i, out idAsInt)) { - var exists = publishedContentExists(int.Parse(i)); + var exists = publishedContentExists(int.Parse(i, CultureInfo.InvariantCulture)); if (exists) return idAsInt; } diff --git a/src/Umbraco.Infrastructure/Events/RelateOnTrashNotificationHandler.cs b/src/Umbraco.Infrastructure/Events/RelateOnTrashNotificationHandler.cs index df0f074ea3..4222ac800e 100644 --- a/src/Umbraco.Infrastructure/Events/RelateOnTrashNotificationHandler.cs +++ b/src/Umbraco.Infrastructure/Events/RelateOnTrashNotificationHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System.Globalization; using System.Linq; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -72,7 +73,7 @@ namespace Umbraco.Cms.Core.Events { var originalPath = item.OriginalPath.ToDelimitedList(); var originalParentId = originalPath.Count > 2 - ? int.Parse(originalPath[originalPath.Count - 2]) + ? int.Parse(originalPath[originalPath.Count - 2], CultureInfo.InvariantCulture) : Constants.System.Root; //before we can create this relation, we need to ensure that the original parent still exists which @@ -130,7 +131,7 @@ namespace Umbraco.Cms.Core.Events { var originalPath = item.OriginalPath.ToDelimitedList(); var originalParentId = originalPath.Count > 2 - ? int.Parse(originalPath[originalPath.Count - 2]) + ? int.Parse(originalPath[originalPath.Count - 2], CultureInfo.InvariantCulture) : Constants.System.Root; //before we can create this relation, we need to ensure that the original parent still exists which //may not be the case if the encompassing transaction also deleted it when this item was moved to the bin diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index 05ceef6697..776af6531c 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Text; @@ -323,8 +324,8 @@ namespace Umbraco.Cms.Infrastructure.Packaging parentId, contentType, key, - int.Parse(level), - int.Parse(sortOrder), + int.Parse(level, CultureInfo.InvariantCulture), + int.Parse(sortOrder, CultureInfo.InvariantCulture), template?.Id); // Handle culture specific node names @@ -1323,7 +1324,7 @@ namespace Umbraco.Cms.Infrastructure.Packaging var cacheDuration = 0; if (cacheDurationElement != null && string.IsNullOrEmpty((string)cacheDurationElement) == false) { - cacheDuration = int.Parse(cacheDurationElement.Value); + cacheDuration = int.Parse(cacheDurationElement.Value, CultureInfo.InvariantCulture); } var cacheByMemberElement = macroElement.Element("cacheByMember"); var cacheByMember = false; @@ -1364,7 +1365,7 @@ namespace Umbraco.Cms.Infrastructure.Packaging XAttribute sortOrderAttribute = property.Attribute("sortOrder"); if (sortOrderAttribute != null) { - sortOrder = int.Parse(sortOrderAttribute.Value); + sortOrder = int.Parse(sortOrderAttribute.Value, CultureInfo.InvariantCulture); } if (macro.Properties.Values.Any(x => string.Equals(x.Alias, propertyAlias, StringComparison.OrdinalIgnoreCase))) diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/ExternalLoginFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/ExternalLoginFactory.cs index 58819f306a..212973d49c 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/ExternalLoginFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/ExternalLoginFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Infrastructure.Persistence.Dtos; @@ -35,7 +36,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Factories CreateDate = entity.CreateDate, LoginProvider = entity.LoginProvider, ProviderKey = entity.ProviderKey, - UserId = int.Parse(entity.UserId), // TODO: This is temp until we change the ext logins to use GUIDs + UserId = int.Parse(entity.UserId, CultureInfo.InvariantCulture), // TODO: This is temp until we change the ext logins to use GUIDs UserData = entity.UserData }; diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/MacroFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/MacroFactory.cs index 960b809c74..ce871f8761 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/MacroFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/MacroFactory.cs @@ -50,7 +50,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Factories }; if (entity.HasIdentity) - dto.Id = int.Parse(entity.Id.ToString(CultureInfo.InvariantCulture)); + dto.Id = int.Parse(entity.Id.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); return dto; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs index c72e11f595..239f0a89ed 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; @@ -532,7 +533,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement currentParentIds.Add(node.NodeId); // paths parts without the roots - var pathParts = node.Path.Split(Constants.CharArrays.Comma).Where(x => !rootIds.Contains(int.Parse(x))).ToArray(); + var pathParts = node.Path.Split(Constants.CharArrays.Comma).Where(x => !rootIds.Contains(int.Parse(x, CultureInfo.InvariantCulture))).ToArray(); if (!prevParentIds.Contains(node.ParentId)) { diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index f9e8316f70..d93c2c8322 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1344,7 +1344,7 @@ WHERE cmsContentType." + aliasColumn + @" LIKE @pattern", /// public bool HasContainerInPath(string contentPath) { - var ids = contentPath.Split(Constants.CharArrays.Comma).Select(int.Parse).ToArray(); + var ids = contentPath.Split(Constants.CharArrays.Comma).Select(s => int.Parse(s, CultureInfo.InvariantCulture)).ToArray(); return HasContainerInPath(ids); } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs index 0353106e17..1ed8404f78 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.Extensions.Logging; using NPoco; @@ -941,7 +942,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement if (content.ParentId == -1) return content.Published; - var ids = content.Path.Split(Constants.CharArrays.Comma).Skip(1).Select(int.Parse); + var ids = content.Path.Split(Constants.CharArrays.Comma).Skip(1).Select(s => int.Parse(s, CultureInfo.InvariantCulture)); var sql = SqlContext.Sql() .SelectCount(x => x.NodeId) diff --git a/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs b/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs index e3ddc69e6f..ebd12719e1 100644 --- a/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Identity; using Umbraco.Cms.Core.Configuration.Models; @@ -157,6 +158,6 @@ namespace Umbraco.Cms.Core.Security Roles = roles; } - private static string UserIdToString(int userId) => string.Intern(userId.ToString()); + private static string UserIdToString(int userId) => string.Intern(userId.ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs index dceae58446..15490bcd04 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs @@ -535,7 +535,8 @@ namespace Umbraco.Cms.Core.Services.Implement var rootId = Cms.Core.Constants.System.RootString; var ids = content.Path.Split(Constants.CharArrays.Comma) - .Where(x => x != rootId && x != content.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray(); + .Where(x => x != rootId && x != content.Id.ToString(CultureInfo.InvariantCulture)).Select(s => + int.Parse(s, CultureInfo.InvariantCulture)).ToArray(); if (ids.Any() == false) return new List(); diff --git a/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs b/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs index 0239ad8e60..0aa49cde44 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs @@ -485,7 +485,7 @@ namespace Umbraco.Cms.Core.Services.Implement var rootId = Cms.Core.Constants.System.RootString; var ids = media.Path.Split(Constants.CharArrays.Comma) .Where(x => x != rootId && x != media.Id.ToString(CultureInfo.InvariantCulture)) - .Select(int.Parse) + .Select(s => int.Parse(s, CultureInfo.InvariantCulture)) .ToArray(); if (ids.Any() == false) return new List(); diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index dc45319d12..447143092a 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -83,7 +83,7 @@ namespace Umbraco.Cms.Core.Services.Implement if (entitiesL.Count == 0) return; //put all entity's paths into a list with the same indices - var paths = entitiesL.Select(x => x.Path.Split(Constants.CharArrays.Comma).Select(int.Parse).ToArray()).ToArray(); + var paths = entitiesL.Select(x => x.Path.Split(Constants.CharArrays.Comma).Select(s => int.Parse(s, CultureInfo.InvariantCulture)).ToArray()).ToArray(); // lazily get versions var prevVersionDictionary = new Dictionary(); diff --git a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs index f26b53775f..875e6d2ffc 100644 --- a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs +++ b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs @@ -82,7 +82,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache var pos = route.IndexOf('/'); var path = pos == 0 ? route : route.Substring(pos); - var startNodeId = pos == 0 ? 0 : int.Parse(route.Substring(0, pos)); + var startNodeId = pos == 0 ? 0 : int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture); var parts = path.Split(Constants.CharArrays.ForwardSlash, StringSplitOptions.RemoveEmptyEntries); IPublishedContent content; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/TryConvertToTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/TryConvertToTests.cs index 0525a24173..5d1c0364b1 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/TryConvertToTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/TryConvertToTests.cs @@ -2,6 +2,7 @@ // See LICENSE for more details. using System; +using System.Globalization; using NUnit.Framework; using Umbraco.Extensions; @@ -46,10 +47,28 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.CoreThings Assert.AreEqual(false, conv.Result); } + [Test] - public void ConvertToIntegerTest() + [TestCase("en-US")] + [TestCase(null)] + [TestCase("sv-SE")] + [TestCase("da-DK")] + [TestCase("tr-TR")] + public void ConvertToIntegerTest(string culture) { - var conv = "100".TryConvertTo(); + if (culture is not null) + { + CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(culture); + } + var conv = "-1".TryConvertTo(); + Assert.IsTrue(conv); + Assert.AreEqual(-1, conv.Result); + + conv = "−1".TryConvertTo(); + Assert.IsTrue(conv); + Assert.AreEqual(-1, conv.Result); + + conv = "100".TryConvertTo(); Assert.IsTrue(conv); Assert.AreEqual(100, conv.Result); diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 8ee4ee1182..4d0e2cfe14 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net.Http; using Microsoft.AspNetCore.Authorization; @@ -202,7 +203,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public ActionResult PostSave(DictionarySave dictionary) { var dictionaryItem = - _localizationService.GetDictionaryItemById(int.Parse(dictionary.Id.ToString())); + _localizationService.GetDictionaryItemById(int.Parse(dictionary.Id.ToString(), CultureInfo.InvariantCulture)); if (dictionaryItem == null) return ValidationProblem("Dictionary item does not exist"); diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index 944f1946bf..4f380b1bcf 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Http; @@ -218,7 +219,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return foundContentResult; } - return new ActionResult>(foundContent.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse)); + return new ActionResult>(foundContent.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Select( + s => int.Parse(s, CultureInfo.InvariantCulture))); } /// @@ -236,7 +238,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return foundContentResult; } - return new ActionResult>(foundContent.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse)); + return new ActionResult>(foundContent.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Select( + s => int.Parse(s, CultureInfo.InvariantCulture))); } /// @@ -859,7 +862,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers { // TODO: Need to check for Object types that support hierarchic here, some might not. - var ids = _entityService.Get(id).Path.Split(Constants.CharArrays.Comma).Select(int.Parse).Distinct().ToArray(); + var ids = _entityService.Get(id).Path.Split(Constants.CharArrays.Comma).Select(s => int.Parse(s, CultureInfo.InvariantCulture)).Distinct().ToArray(); var ignoreUserStartNodes = IsDataTypeIgnoringUserStartNodes(queryStrings?.GetValue("dataTypeId")); if (ignoreUserStartNodes == false) diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs index 84ff7565cc..834d8cc565 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -184,7 +185,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return ValidationProblem("Name cannnot be more than 255 characters in length."); } - var macro = _macroService.GetById(int.Parse(macroDisplay.Id.ToString())); + var macro = _macroService.GetById(int.Parse(macroDisplay.Id.ToString(), CultureInfo.InvariantCulture)); if (macro == null) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs index 81303ba55e..fb5286505e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -122,7 +123,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public ActionResult PostSave(MemberGroupSave saveModel) { - var id = int.Parse(saveModel.Id.ToString()); + var id = int.Parse(saveModel.Id.ToString(), CultureInfo.InvariantCulture); IMemberGroup memberGroup = id > 0 ? _memberGroupService.GetById(id) : new MemberGroup(); if (memberGroup == null) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs index 7f5298066a..d0aadac744 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Text; using Umbraco.Cms.Core; @@ -189,7 +190,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers switch (condition.Property.Type) { case "int": - return int.Parse(condition.ConstraintValue); + return int.Parse(condition.ConstraintValue, CultureInfo.InvariantCulture); case "datetime": DateTime dt; return DateTime.TryParse(condition.ConstraintValue, out dt) ? dt : DateTime.Today; diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs index 9b6ccf91f6..abf3854f5b 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -130,7 +131,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var cte = _entityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentType); + var cte = _entityService.Get(int.Parse(id, CultureInfo.InvariantCulture), UmbracoObjectTypes.DocumentType); //only refresh & create if it's a content type if (cte != null) { diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs index 2ba9e5f6c7..024be6647e 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -125,7 +126,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees return menu; } - var container = _entityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentTypeContainer); + var container = _entityService.Get(int.Parse(id, CultureInfo.InvariantCulture), UmbracoObjectTypes.DocumentTypeContainer); if (container != null) { //set the default to create @@ -147,7 +148,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees } else { - var ct = _contentTypeService.Get(int.Parse(id)); + var ct = _contentTypeService.Get(int.Parse(id, CultureInfo.InvariantCulture)); var parent = ct == null ? null : _contentTypeService.Get(ct.ParentId); menu.Items.Add(LocalizedTextService, opensDialog: true); diff --git a/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs index bddf823c43..d83a813de6 100644 --- a/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -134,7 +135,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees return menu; } - var container = _entityService.Get(int.Parse(id), UmbracoObjectTypes.DataTypeContainer); + var container = _entityService.Get(int.Parse(id, CultureInfo.InvariantCulture), UmbracoObjectTypes.DataTypeContainer); if (container != null) { //set the default to create @@ -158,7 +159,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees { var nonDeletableSystemDataTypeIds = GetNonDeletableSystemDataTypeIds(); - if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id)) == false) + if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id, CultureInfo.InvariantCulture)) == false) menu.Items.Add(LocalizedTextService, opensDialog: true); menu.Items.Add(LocalizedTextService, hasSeparator: true, opensDialog: true); diff --git a/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs index c29518473d..d90a53c8e2 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -79,7 +80,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees return menu; } - var macro = _macroService.GetById(int.Parse(id)); + var macro = _macroService.GetById(int.Parse(id, CultureInfo.InvariantCulture)); if (macro == null) return menu; //add delete option for all macros diff --git a/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs index 2cda5802b8..7a6c70650a 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -97,7 +98,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees return menu; } - var container = _entityService.Get(int.Parse(id), UmbracoObjectTypes.MediaTypeContainer); + var container = _entityService.Get(int.Parse(id, CultureInfo.InvariantCulture), UmbracoObjectTypes.MediaTypeContainer); if (container != null) { // set the default to create @@ -119,7 +120,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees } else { - var ct = _mediaTypeService.Get(int.Parse(id)); + var ct = _mediaTypeService.Get(int.Parse(id, CultureInfo.InvariantCulture)); var parent = ct == null ? null : _mediaTypeService.Get(ct.ParentId); menu.Items.Add(LocalizedTextService, opensDialog: true); diff --git a/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs index 6da2298e03..22f96fa7c8 100644 --- a/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -51,7 +52,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees return menu; } - var relationType = _relationService.GetRelationTypeById(int.Parse(id)); + var relationType = _relationService.GetRelationTypeById(int.Parse(id, CultureInfo.InvariantCulture)); if (relationType == null) return menu; if (relationType.IsSystemRelationType() == false) diff --git a/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs index 4c91edbf45..e017f0e6d0 100644 --- a/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs @@ -76,7 +76,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees var found = id == Constants.System.RootString ? _fileService.GetTemplates(-1) - : _fileService.GetTemplates(int.Parse(id)); + : _fileService.GetTemplates(int.Parse(id, CultureInfo.InvariantCulture)); nodes.AddRange(found.Select(template => CreateTreeNode( template.Id.ToString(CultureInfo.InvariantCulture), @@ -115,7 +115,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees return menu; } - var template = _fileService.GetTemplate(int.Parse(id)); + var template = _fileService.GetTemplate(int.Parse(id, CultureInfo.InvariantCulture)); if (template == null) return menu; var entity = FromTemplate(template); diff --git a/src/Umbraco.Web.Common/Security/MemberManager.cs b/src/Umbraco.Web.Common/Security/MemberManager.cs index f7d0c8e43e..9a0f26aff4 100644 --- a/src/Umbraco.Web.Common/Security/MemberManager.cs +++ b/src/Umbraco.Web.Common/Security/MemberManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -82,7 +83,7 @@ namespace Umbraco.Cms.Web.Common.Security return false; } - int memberId = int.Parse(currentMember.Id); + int memberId = int.Parse(currentMember.Id, CultureInfo.InvariantCulture); username = currentMember.UserName; // If types defined, check member is of one of those types @@ -192,7 +193,7 @@ namespace Umbraco.Cms.Web.Common.Security if (currentMember == null || !currentMember.IsApproved || currentMember.IsLockedOut) { return false; - } + } return await _publicAccessService.HasAccessAsync( path, @@ -231,7 +232,7 @@ namespace Umbraco.Cms.Web.Common.Security async () => await getUserRolesAsync()); } return result; - } + } public IPublishedContent AsPublishedMember(MemberIdentityUser user) => _store.GetPublishedMember(user); }