./ paths relative on page.
This commit is contained in:
parent
2d2ed571df
commit
42b988ad88
|
|
@ -11,6 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
|||
{
|
||||
public static class ViewEnginePath
|
||||
{
|
||||
private const string CurrentDirectoryToken = ".";
|
||||
private const string ParentDirectoryToken = "..";
|
||||
private static readonly char[] _pathSeparators = new[] { '/', '\\' };
|
||||
|
||||
|
|
@ -70,6 +71,11 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
|||
}
|
||||
pathSegments.RemoveAt(pathSegments.Count - 1);
|
||||
}
|
||||
else if (segment.Equals(CurrentDirectoryToken, StringComparison.Ordinal))
|
||||
{
|
||||
// We already have the current directory
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathSegments.Add(segment);
|
||||
|
|
@ -89,7 +95,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
|||
|
||||
private static bool RequiresPathResolution(string path)
|
||||
{
|
||||
return path.IndexOf(ParentDirectoryToken, StringComparison.Ordinal) != -1;
|
||||
return path.IndexOf(ParentDirectoryToken, StringComparison.Ordinal) != -1 ||
|
||||
path.IndexOf(CurrentDirectoryToken, StringComparison.Ordinal) != -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -404,6 +404,6 @@
|
|||
<value>No page named '{0}' matches the supplied values.</value>
|
||||
</data>
|
||||
<data name="UrlHelper_RelativePagePathIsNotSupported" xml:space="preserve">
|
||||
<value>The relative page path '{0}' can only can only be used while executing a Razor Page. Specify a root relative path with a leading '/' to generate a URL outside of a Razor Page.</value>
|
||||
<value>The relative page path '{0}' can only be used while executing a Razor Page. Specify a root relative path with a leading '/' to generate a URL outside of a Razor Page.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -77,6 +77,63 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
httpResponse.Verify(r => r.Redirect(expectedUrl, permanentRedirect), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_LocalRelativePaths()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext
|
||||
{
|
||||
RequestServices = CreateServices(),
|
||||
};
|
||||
|
||||
var pageContext = new PageContext
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
RouteData = new RouteData(),
|
||||
ActionDescriptor = new CompiledPageActionDescriptor(),
|
||||
};
|
||||
|
||||
pageContext.RouteData.Values.Add("page", "/A/Redirecting/Page");
|
||||
|
||||
UrlRouteContext context = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext).Returns(pageContext);
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext c) => context = c)
|
||||
.Returns("some-value");
|
||||
var values = new { test = "test-value" };
|
||||
var result = new RedirectToPageResult("./", "page-handler", values, true, "test-fragment")
|
||||
{
|
||||
UrlHelper = urlHelper.Object,
|
||||
Protocol = "ftp",
|
||||
};
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(pageContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(context);
|
||||
Assert.Null(context.RouteName);
|
||||
Assert.Collection(Assert.IsType<RouteValueDictionary>(context.Values),
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("test", value.Key);
|
||||
Assert.Equal("test-value", value.Value);
|
||||
},
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("page", value.Key);
|
||||
Assert.Equal("/A/Redirecting", value.Value);
|
||||
},
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("handler", value.Key);
|
||||
Assert.Equal("page-handler", value.Value);
|
||||
});
|
||||
Assert.Equal("ftp", context.Protocol);
|
||||
Assert.Equal("test-fragment", context.Fragment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_WithAllParameters()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1518,7 +1518,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
|
|||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => urlHelper.Object.Page(expected));
|
||||
Assert.Equal($"The relative page path '{expected}' can only can only be used while executing a Razor Page. " +
|
||||
Assert.Equal($"The relative page path '{expected}' can only be used while executing a Razor Page. " +
|
||||
"Specify a root relative path with a leading '/' to generate a URL outside of a Razor Page.", ex.Message);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -924,6 +924,20 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore._InjectedP
|
|||
Assert.Equal(expected, response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RedirectToSibling_RedirectsToDotSlash()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "/Pages/Redirects/SubDir/SubDirPage";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("/Pages/Redirects/RedirectToSibling/RedirectToDotSlash");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||
Assert.Equal(expected, response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RedirectToSibling_RedirectsToParentDirectory()
|
||||
{
|
||||
|
|
@ -940,8 +954,8 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore._InjectedP
|
|||
public async Task TagHelpers_SupportSiblingRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var expected =
|
||||
@"<form method=""post"" action=""/Pages/TagHelper/CrossPost""></form>
|
||||
var expected =
|
||||
@"<form method=""post"" action=""/Pages/TagHelper/CrossPost""></form>
|
||||
<a href=""/Pages/TagHelper/SelfPost/12"" />
|
||||
<input type=""image"" formaction=""/Pages/TagHelper/CrossPost#my-fragment"" />";
|
||||
|
||||
|
|
@ -956,8 +970,8 @@ var expected =
|
|||
public async Task TagHelpers_SupportSubDirectoryRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var expected =
|
||||
@"<form method=""post"" action=""/Pages/TagHelper/SubDir/SubDirPage""></form>
|
||||
var expected =
|
||||
@"<form method=""post"" action=""/Pages/TagHelper/SubDir/SubDirPage""></form>
|
||||
<a href=""/Pages/TagHelper/SubDir/SubDirPage/12"" />
|
||||
<input type=""image"" formaction=""/Pages/TagHelper/SubDir/SubDirPage#my-fragment"" />";
|
||||
|
||||
|
|
@ -972,8 +986,8 @@ var expected =
|
|||
public async Task TagHelpers_SupportsPathNavigation()
|
||||
{
|
||||
// Arrange
|
||||
var expected =
|
||||
@"<form method=""post"" action=""/HelloWorld""></form>
|
||||
var expected =
|
||||
@"<form method=""post"" action=""/HelloWorld""></form>
|
||||
<a href=""/Pages/Redirects/RedirectToIndex"" />
|
||||
<input type=""image"" formaction=""/Pages/Admin#my-fragment"" />";
|
||||
|
||||
|
|
@ -981,7 +995,20 @@ var expected =
|
|||
var response = await Client.GetStringAsync("/Pages/TagHelper/PathTraversalLinks");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, response.Trim());
|
||||
Assert.EndsWith(expected, response.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TagHelpers_SupportsRelativeNavigation()
|
||||
{
|
||||
// Arrange
|
||||
var expected = @"<form method=""post"" action=""/Pages/TagHelper/SubDirectoryLinks""></form>";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetStringAsync("/Pages/TagHelper/PathTraversalLinks");
|
||||
|
||||
// Assert
|
||||
Assert.StartsWith(expected, response.Trim());
|
||||
}
|
||||
|
||||
private async Task AddAntiforgeryHeaders(HttpRequestMessage request)
|
||||
|
|
|
|||
|
|
@ -1472,6 +1472,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
|||
[InlineData("/Views/Home/Index.cshtml", "..\\Shared\\_Partial.cshtml")]
|
||||
[InlineData("/Areas/MyArea/Views/Home/Index.cshtml", "../../../../Views/Shared/_Partial.cshtml")]
|
||||
[InlineData("/Views/Accounts/Users.cshtml", "../Test/../Shared/_Partial.cshtml")]
|
||||
[InlineData("Views/Accounts/Users.cshtml", "./../Shared/./_Partial.cshtml")]
|
||||
public void GetAbsolutePath_ResolvesPathTraversals(string executingFilePath, string pagePath)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@
|
|||
public IActionResult OnGetRedirectToSubDir() => RedirectToPage("SubDir/SubDirPage");
|
||||
|
||||
public IActionResult OnGetRedirectToParent() => RedirectToPage("../Conventions/AuthFolder/Index");
|
||||
|
||||
public IActionResult OnGetRedirectToDotSlash() => RedirectToPage("./SubDir/SubDirPage");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
@page
|
||||
|
||||
<form method="post" asp-page="./SubDirectoryLinks" asp-antiforgery="false"></form>
|
||||
<form method="post" asp-page="../../HelloWorld" asp-antiforgery="false"></form>
|
||||
<a asp-page="../Redirects/Index" asp-route-handler="RedirectToIndex" />
|
||||
<input type="image" asp-page="../Admin/Index" asp-fragment="my-fragment" />
|
||||
<input type="image" asp-page="../Admin/Index" asp-fragment="my-fragment" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue