#19071: Replacing UrlHelper.IsLocalUrl by custom implementation

Work Item: 19071

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2012-10-05 15:05:12 -07:00
parent b33d6081d3
commit 889709239f
5 changed files with 120 additions and 7 deletions

View File

@@ -309,6 +309,7 @@
<Compile Include="UI\Navigation\MenuItemComparerTests.cs" /> <Compile Include="UI\Navigation\MenuItemComparerTests.cs" />
<Compile Include="UI\Navigation\NavigationManagerTests.cs" /> <Compile Include="UI\Navigation\NavigationManagerTests.cs" />
<Compile Include="UI\Navigation\PositionComparerTests.cs" /> <Compile Include="UI\Navigation\PositionComparerTests.cs" />
<Compile Include="Utility\Extensions\HttpRequestExtensionsTests.cs" />
<Compile Include="Utility\Extensions\RouteValueDictionaryExtensionsTests.cs" /> <Compile Include="Utility\Extensions\RouteValueDictionaryExtensionsTests.cs" />
<Compile Include="Utility\Extensions\StringExtensionsTests.cs" /> <Compile Include="Utility\Extensions\StringExtensionsTests.cs" />
<Compile Include="Utility\ReflectOnTests.cs" /> <Compile Include="Utility\ReflectOnTests.cs" />

View File

@@ -0,0 +1,78 @@
using System.Collections.Specialized;
using System.Web;
using NUnit.Framework;
using Orchard.Utility.Extensions;
namespace Orchard.Tests.Utility.Extensions {
[TestFixture]
public class HttpRequestExtensionsTests {
[Test]
public void IsLocalUrlShouldReturnFalseWhenUrlIsNullOrEmpty() {
var request = new StubHttpRequest();
Assert.That(request.IsLocalUrl(null), Is.False);
Assert.That(request.IsLocalUrl(" "), Is.False);
Assert.That(request.IsLocalUrl(""), Is.False);
}
[Test]
public void IsLocalUrlShouldReturnFalseWhenUrlStartsWithDoubleSlash() {
var request = new StubHttpRequest();
Assert.That(request.IsLocalUrl("//"), Is.False);
}
[Test]
public void IsLocalUrlShouldReturnFalseWhenUrlStartsWithForwardBackwardSlash() {
var request = new StubHttpRequest();
Assert.That(request.IsLocalUrl("/\\"), Is.False);
}
[Test]
public void IsLocalUrlShouldReturnTrueWhenUrlStartsWithSlashAndAnythingElse() {
var request = new StubHttpRequest();
Assert.That(request.IsLocalUrl("/"), Is.True);
Assert.That(request.IsLocalUrl("/контакты"), Is.True);
Assert.That(request.IsLocalUrl("/ "), Is.True);
Assert.That(request.IsLocalUrl("/abc-def"), Is.True);
}
[Test]
public void IsLocalUrlShouldReturnTrueWhenAuthoritiesMatch() {
var request = new StubHttpRequest();
request.Headers.Add("Host", "localhost");
Assert.That(request.IsLocalUrl("http://localhost"), Is.True);
}
[Test]
public void IsLocalUrlShouldReturnFalseWhenAuthoritiesDiffer() {
var request = new StubHttpRequest();
request.Headers.Add("Host", "localhost");
Assert.That(request.IsLocalUrl("http://somedomain"), Is.False);
Assert.That(request.IsLocalUrl("http://localhost:8080"), Is.False);
}
[Test]
public void IsLocalUrlShouldReturnFalseForEverythingElse() {
var request = new StubHttpRequest();
request.Headers.Add("Host", "localhost");
Assert.That(request.IsLocalUrl("abc"), Is.False);
}
}
class StubHttpRequest : HttpRequestBase {
private readonly NameValueCollection _headers = new NameValueCollection();
public override NameValueCollection Headers {
get {
return _headers;
}
}
}
}

View File

@@ -21,6 +21,7 @@ using Orchard.Mvc.Html;
using Orchard.UI.Navigation; using Orchard.UI.Navigation;
using Orchard.UI.Notify; using Orchard.UI.Notify;
using Orchard.Settings; using Orchard.Settings;
using Orchard.Utility.Extensions;
namespace Orchard.Core.Contents.Controllers { namespace Orchard.Core.Contents.Controllers {
[ValidateInput(false)] [ValidateInput(false)]
@@ -299,7 +300,7 @@ namespace Orchard.Core.Contents.Controllers {
string previousRoute = null; string previousRoute = null;
if(contentItem.Has<IAliasAspect>() if(contentItem.Has<IAliasAspect>()
&&!string.IsNullOrWhiteSpace(returnUrl) &&!string.IsNullOrWhiteSpace(returnUrl)
&& Url.IsLocalUrl(returnUrl) && Request.IsLocalUrl(returnUrl)
// only if the original returnUrl is the content itself // only if the original returnUrl is the content itself
&& String.Equals(returnUrl, Url.ItemDisplayUrl(contentItem), StringComparison.OrdinalIgnoreCase) && String.Equals(returnUrl, Url.ItemDisplayUrl(contentItem), StringComparison.OrdinalIgnoreCase)
) { ) {

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using Orchard.Utility.Extensions;
namespace Orchard.Mvc.Extensions { namespace Orchard.Mvc.Extensions {
public static class ControllerExtensions { public static class ControllerExtensions {
@@ -15,14 +17,10 @@ namespace Orchard.Mvc.Extensions {
} }
public static ActionResult RedirectLocal(this Controller controller, string redirectUrl, string defaultUrl) { public static ActionResult RedirectLocal(this Controller controller, string redirectUrl, string defaultUrl) {
if (!string.IsNullOrWhiteSpace(redirectUrl) if (controller.Request.IsLocalUrl(redirectUrl)) {
&& controller.Url.IsLocalUrl(redirectUrl)
&& !redirectUrl.StartsWith("//")
&& !redirectUrl.StartsWith("/\\")) {
return new RedirectResult(redirectUrl); return new RedirectResult(redirectUrl);
} }
return new RedirectResult(defaultUrl ?? "~/"); return new RedirectResult(defaultUrl ?? "~/");
} }
} }

View File

@@ -1,3 +1,4 @@
using System;
using System.Web; using System.Web;
namespace Orchard.Utility.Extensions { namespace Orchard.Utility.Extensions {
@@ -57,5 +58,39 @@ namespace Orchard.Utility.Extensions {
public static string ToUrlString(this HttpRequest request) { public static string ToUrlString(this HttpRequest request) {
return string.Format("{0}://{1}{2}", request.Url.Scheme, request.Headers["Host"], request.RawUrl); return string.Format("{0}://{1}{2}", request.Url.Scheme, request.Headers["Host"], request.RawUrl);
} }
/// <summary>
/// Returns wether the specified url is local to the host or not
/// </summary>
/// <param name="request"></param>
/// <param name="url"></param>
/// <returns></returns>
public static bool IsLocalUrl(this HttpRequestBase request, string url) {
if (string.IsNullOrWhiteSpace(url)) {
return false;
}
if (url.StartsWith("//") || url.StartsWith("/\\")) {
return false;
}
// at this point is the url starts with "/" it is local
if (url.StartsWith("/")) {
return true;
}
// at this point, check for an fully qualified url
try {
var uri = new Uri(url);
return uri.Authority.Equals(request.Headers["Host"], StringComparison.OrdinalIgnoreCase);
}
catch {
// mall-formed url e.g, "abcdef"
return false;
}
}
} }
} }