From f1a439e8512b655728ea71d82ffdceabbddcf950 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 18 Feb 2014 14:57:03 +1100 Subject: [PATCH] removes version specific references to mysql in the proj files and web.config ensures that escaping in the sql expression classes is done correctly without any double escaping. Also ensures that escaping is happening using the equals operator, not just the Equals() method and adds unit tests for them. Fixes: U4-4232 Umbraco.Core.Persistence.Querying issue with backslashes --- .../Querying/ModelToSqlExpressionHelper.cs | 10 ++-- .../Querying/PocoToSqlExpressionHelper.cs | 6 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 +- src/Umbraco.Core/packages.config | 2 +- .../Persistence/Querying/ExpressionTests.cs | 58 +++++++++++++++++++ src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- .../config/ClientDependency.config | 2 +- src/Umbraco.Web.UI/web.Template.config | 4 +- .../umbraco.datalayer.csproj | 2 +- 9 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs index c7797d1a20..6ab3fcc592 100644 --- a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs @@ -232,15 +232,15 @@ namespace Umbraco.Core.Persistence.Querying switch (verb) { case "SqlWildcard": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, EscapeParam(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, RemoveQuote(val), columnType); case "Equals": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, EscapeParam(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, RemoveQuote(val), columnType); case "StartsWith": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, EscapeParam(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, RemoveQuote(val), columnType); case "EndsWith": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, EscapeParam(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, RemoveQuote(val), columnType); case "Contains": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, EscapeParam(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, RemoveQuote(val), columnType); case "InvariantEquals": case "SqlEquals": //recurse diff --git a/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs index 22bfed1e82..ecd5bb0087 100644 --- a/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs @@ -254,11 +254,11 @@ namespace Umbraco.Core.Persistence.Querying case "ToLower": return string.Format("lower({0})", r); case "StartsWith": - return string.Format("upper({0}) like '{1}%'", r, EscapeParam(RemoveQuote(args[0].ToString().ToUpper()))); + return string.Format("upper({0}) like '{1}%'", r, RemoveQuote(args[0].ToString().ToUpper())); case "EndsWith": - return string.Format("upper({0}) like '%{1}'", r, EscapeParam(RemoveQuote(args[0].ToString()).ToUpper())); + return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper()); case "Contains": - return string.Format("upper({0}) like '%{1}%'", r, EscapeParam(RemoveQuote(args[0].ToString()).ToUpper())); + return string.Format("upper({0}) like '%{1}%'", r, RemoveQuote(args[0].ToString()).ToUpper()); case "Substring": var startIndex = Int32.Parse(args[0].ToString()) + 1; if (args.Count == 2) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b9e13a86fd..d4f6d29c27 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -45,9 +45,9 @@ ..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll - + False - ..\packages\MySql.Data.6.8.3\lib\net40\MySql.Data.dll + ..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll ..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll diff --git a/src/Umbraco.Core/packages.config b/src/Umbraco.Core/packages.config index 3b2d7e5ca2..3b24cc962d 100644 --- a/src/Umbraco.Core/packages.config +++ b/src/Umbraco.Core/packages.config @@ -6,7 +6,7 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs b/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs index c0316e979e..ba1592635f 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs @@ -2,7 +2,10 @@ using System.Linq.Expressions; using NUnit.Framework; using Umbraco.Core.Models; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Persistence.Querying @@ -35,5 +38,60 @@ namespace Umbraco.Tests.Persistence.Querying Assert.AreEqual("[umbracoNode].[parentID] = -1", result); } + + [Test] + public void Equals_Operator_For_Value_Gets_Escaped() + { + Expression> predicate = user => user.Username == "hello@world.com"; + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(); + var result = modelToSqlExpressionHelper.Visit(predicate); + + Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); + + Assert.AreEqual("[umbracoUser].[userLogin] = 'hello@@world.com'", result); + } + + [Test] + public void Equals_Method_For_Value_Gets_Escaped() + { + Expression> predicate = user => user.Username.Equals("hello@world.com"); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(); + var result = modelToSqlExpressionHelper.Visit(predicate); + + Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); + + Assert.AreEqual("upper([umbracoUser].[userLogin]) = 'HELLO@@WORLD.COM'", result); + } + + [Test] + public void Model_Expression_Value_Does_Not_Get_Double_Escaped() + { + //mysql escapes backslashes, so we'll test with that + SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; + + Expression> predicate = user => user.Username.Equals("mydomain\\myuser"); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(); + var result = modelToSqlExpressionHelper.Visit(predicate); + + Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); + + Assert.AreEqual("upper(`umbracoUser`.`userLogin`) = 'MYDOMAIN\\\\MYUSER'", result); + } + + [Test] + public void Poco_Expression_Value_Does_Not_Get_Double_Escaped() + { + //mysql escapes backslashes, so we'll test with that + SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; + + Expression> predicate = user => user.Login.StartsWith("mydomain\\myuser"); + var modelToSqlExpressionHelper = new PocoToSqlExpressionHelper(); + var result = modelToSqlExpressionHelper.Visit(predicate); + + Console.WriteLine("Poco to Sql ExpressionHelper: \n" + result); + + Assert.AreEqual("upper(`umbracoUser`.`userLogin`) like 'MYDOMAIN\\\\MYUSER%'", result); + } + } } \ 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 63ebcd4e16..4045d404a9 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -132,7 +132,7 @@ False ..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll - + False ..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll diff --git a/src/Umbraco.Web.UI/config/ClientDependency.config b/src/Umbraco.Web.UI/config/ClientDependency.config index 6c1ff881cf..f2f058cd14 100644 --- a/src/Umbraco.Web.UI/config/ClientDependency.config +++ b/src/Umbraco.Web.UI/config/ClientDependency.config @@ -10,7 +10,7 @@ NOTES: * Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config * A new version will invalidate both client and server cache and create new persisted files --> - +