Skip to content

Commit 5e5fab7

Browse files
Merge pull request #279 from jrunestone/278-special-characters
Url decode path before fetching from file system, fixes #278
2 parents 20fbfae + 92a3b3b commit 5e5fab7

File tree

6 files changed

+52
-8
lines changed

6 files changed

+52
-8
lines changed

src/ImageSharp.Web/CaseHandlingUriBuilder.cs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ public static string BuildAbsolute(
6666
PathString path = default,
6767
QueryString query = default)
6868
{
69-
string hostText = host.ToString();
70-
string pathBaseText = pathBase.ToString();
71-
string pathText = path.ToString();
72-
string queryText = query.ToString();
69+
string hostText = host.ToUriComponent();
70+
string pathBaseText = pathBase.ToUriComponent();
71+
string pathText = path.ToUriComponent();
72+
string queryText = query.ToUriComponent();
7373

7474
// PERF: Calculate string length to allocate correct buffer size for string.Create.
7575
int length =
@@ -97,6 +97,46 @@ public static string BuildAbsolute(
9797
return string.Create(length, (handling == CaseHandling.LowerInvariant, hostText, pathBaseText, pathText, queryText), InitializeAbsoluteUriStringSpanAction);
9898
}
9999

100+
/// <summary>
101+
/// Generates a string from the given absolute or relative Uri that is appropriately encoded for use in
102+
/// HTTP headers. Note that a unicode host name will be encoded as punycode.
103+
/// </summary>
104+
/// <param name="handling">Determines case handling for the result.</param>
105+
/// <param name="uri">The Uri to encode.</param>
106+
/// <returns>The encoded string version of <paramref name="uri"/>.</returns>
107+
public static string Encode(CaseHandling handling, string uri)
108+
=> Encode(handling, new Uri(uri, UriKind.RelativeOrAbsolute));
109+
110+
/// <summary>
111+
/// Generates a string from the given absolute or relative Uri that is appropriately encoded for use in
112+
/// HTTP headers. Note that a unicode host name will be encoded as punycode.
113+
/// </summary>
114+
/// <param name="handling">Determines case handling for the result.</param>
115+
/// <param name="uri">The Uri to encode.</param>
116+
/// <returns>The encoded string version of <paramref name="uri"/>.</returns>
117+
public static string Encode(CaseHandling handling, Uri uri)
118+
{
119+
Guard.NotNull(uri, nameof(uri));
120+
if (uri.IsAbsoluteUri)
121+
{
122+
return BuildAbsolute(
123+
handling,
124+
host: HostString.FromUriComponent(uri),
125+
pathBase: PathString.FromUriComponent(uri),
126+
query: QueryString.FromUriComponent(uri));
127+
}
128+
else
129+
{
130+
string components = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
131+
if (handling == CaseHandling.LowerInvariant)
132+
{
133+
return components.ToLowerInvariant();
134+
}
135+
136+
return components;
137+
}
138+
}
139+
100140
/// <summary>
101141
/// Copies the specified <paramref name="text"/> to the specified <paramref name="buffer"/> starting at the specified <paramref name="index"/>.
102142
/// </summary>

src/ImageSharp.Web/Providers/FileProviderImageProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
5+
using System.Net;
56
using System.Threading.Tasks;
67
using Microsoft.AspNetCore.Http;
78
using Microsoft.AspNetCore.Http.Extensions;
@@ -54,7 +55,7 @@ public virtual bool IsValidRequest(HttpContext context)
5455
/// <inheritdoc/>
5556
public Task<IImageResolver> GetAsync(HttpContext context)
5657
{
57-
IFileInfo fileInfo = this.fileProvider.GetFileInfo(context.Request.Path);
58+
IFileInfo fileInfo = this.fileProvider.GetFileInfo(context.Request.Path.Value);
5859
if (!fileInfo.Exists)
5960
{
6061
return Task.FromResult<IImageResolver>(null);

tests/ImageSharp.Web.Tests/ImageSharp.Web.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</ItemGroup>
1717

1818
<ItemGroup>
19-
<None Update="SubFolder\sixlabors.imagesharp.web.png">
19+
<None Update="SubFolder\sîxläbörs.îmägéshärp.wéb.png">
2020
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2121
</None>
2222
<None Update="xunit.runner.json">

tests/ImageSharp.Web.Tests/SubFolder/sixlabors.imagesharp.web.png renamed to tests/ImageSharp.Web.Tests/SubFolder/sîxläbörs.îmägéshärp.wéb.png

File renamed without changes.

tests/ImageSharp.Web.Tests/TestUtilities/AuthenticatedServerTestBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

4+
using System;
45
using System.Net;
56
using System.Net.Http;
67
using System.Threading.Tasks;
@@ -38,7 +39,9 @@ public async Task CanRejectUnauthorizedRequestAsync()
3839
protected override string AugmentCommand(string command)
3940
{
4041
// Mimic the lowecase relative url format used by the token and default options.
41-
string uri = (this.ImageSource + command).Replace("http://localhost", string.Empty).ToLowerInvariant();
42+
string uri = (this.ImageSource + command).Replace("http://localhost", string.Empty);
43+
uri = CaseHandlingUriBuilder.Encode(CaseHandlingUriBuilder.CaseHandling.LowerInvariant, uri);
44+
4245
string token = HMACUtilities.ComputeHMACSHA256(uri, AuthenticatedTestServerFixture.HMACSecretKey);
4346
return command + "&" + HMACUtilities.TokenCommand + "=" + token;
4447
}

tests/ImageSharp.Web.Tests/TestUtilities/TestConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static class TestConstants
1414
public const string AWSCacheBucketName = "aws-cache";
1515
public const string AWSAccessKey = "";
1616
public const string AWSAccessSecret = "";
17-
public const string ImagePath = "SubFolder/sixlabors.imagesharp.web.png";
17+
public const string ImagePath = "SubFolder/sîxläbörs.îmägéshärp.wéb.png";
1818
public const string PhysicalTestImage = "http://localhost/" + ImagePath;
1919
public const string AzureTestImage = "http://localhost/" + AzureContainerName + "/" + ImagePath;
2020
public const string AWSTestImage = "http://localhost/" + AWSBucketName + "/" + ImagePath;

0 commit comments

Comments
 (0)