Skip to content

Commit 535ab4c

Browse files
authored
Remove cookie name decoding (#368)
1 parent 635c92f commit 535ab4c

File tree

5 files changed

+57
-15
lines changed

5 files changed

+57
-15
lines changed

src/Microsoft.Owin/Infrastructure/OwinHelpers.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -530,13 +530,13 @@ internal static IDictionary<string, string> GetCookies(IOwinRequest request)
530530
if (request.Get<string>("Microsoft.Owin.Cookies#text") != text)
531531
{
532532
cookies.Clear();
533-
ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);
533+
ParseDelimited(text, SemicolonAndComma, AddCookieCallback, decodePlus: false, decodeKey: false, state: cookies);
534534
request.Set("Microsoft.Owin.Cookies#text", text);
535535
}
536536
return cookies;
537537
}
538538

539-
internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)
539+
internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, bool decodePlus, bool decodeKey, object state)
540540
{
541541
int textLength = text.Length;
542542
int equalIndex = text.IndexOf('=');
@@ -560,10 +560,17 @@ internal static void ParseDelimited(string text, char[] delimiters, Action<strin
560560
}
561561
string name = text.Substring(scanIndex, equalIndex - scanIndex);
562562
string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);
563-
callback(
564-
Uri.UnescapeDataString(name.Replace('+', ' ')),
565-
Uri.UnescapeDataString(value.Replace('+', ' ')),
566-
state);
563+
if (decodePlus)
564+
{
565+
name.Replace('+', ' ');
566+
value.Replace('+', ' ');
567+
}
568+
if (decodeKey)
569+
{
570+
name = Uri.UnescapeDataString(name);
571+
}
572+
value = Uri.UnescapeDataString(value);
573+
callback(name, value, state);
567574
equalIndex = text.IndexOf('=', delimiterIndex);
568575
if (equalIndex == -1)
569576
{
@@ -799,7 +806,7 @@ internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)
799806
{
800807
query.Clear();
801808
var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
802-
ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);
809+
ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, decodePlus: true, decodeKey: true, state: accumulator);
803810
foreach (var kv in accumulator)
804811
{
805812
query.Add(kv.Key, kv.Value.ToArray());
@@ -813,7 +820,7 @@ internal static IFormCollection GetForm(string text)
813820
{
814821
IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
815822
var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
816-
ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);
823+
ParseDelimited(text, new[] { '&' }, AppendItemCallback, decodePlus: false, decodeKey: true, state: accumulator);
817824
foreach (var kv in accumulator)
818825
{
819826
form.Add(kv.Key, kv.Value.ToArray());

src/Microsoft.Owin/RequestCookieCollection.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ public string this[string key]
3737
get
3838
{
3939
string value;
40-
Store.TryGetValue(key, out value);
41-
return value;
40+
if (Store.TryGetValue(key, out value) || Store.TryGetValue(Uri.EscapeDataString(key), out value))
41+
{
42+
return value;
43+
}
44+
return null;
4245
}
4346
}
4447

tests/Microsoft.Owin.Tests/FormsTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class FormsTests
1414
private static readonly string[] RawValues = new[] { "v1", "v2, v3", "\"v4, b\"", "v5, v6", "v7", };
1515
private const string JoinedValues = "v1,v2, v3,\"v4, b\",v5, v6,v7";
1616

17-
private const string OriginalFormsString = "q1=v1&q2=v2,b&q3=v3&q3=v4&q4&q5=v5&q5=v5";
17+
private const string OriginalFormsString = "q1=v1&q2=v2,b&q3=v3&q3=v4&q4&q5=v5&q5=v+5";
1818

1919
[Fact]
2020
public void ParseForm()
@@ -30,7 +30,7 @@ public void ParseForm()
3030
Assert.Equal("v2,b", form.Get("Q2"));
3131
Assert.Equal("v3,v4", form.Get("q3"));
3232
Assert.Null(form.Get("q4"));
33-
Assert.Equal("v5,v5", form.Get("Q5"));
33+
Assert.Equal("v5,v+5", form.Get("Q5"));
3434
Assert.True(stream.CanRead);
3535
}
3636

@@ -89,7 +89,7 @@ public void ReadFromStream()
8989
Assert.Equal("v2,b", form.Get("Q2"));
9090
Assert.Equal("v3,v4", form.Get("q3"));
9191
Assert.Null(form.Get("q4"));
92-
Assert.Equal("v5,v5", form.Get("Q5"));
92+
Assert.Equal("v5,v+5", form.Get("Q5"));
9393
}
9494

9595
[Fact]
@@ -107,14 +107,14 @@ public void ReadFromStreamTwice()
107107
Assert.Equal("v2,b", form.Get("Q2"));
108108
Assert.Equal("v3,v4", form.Get("q3"));
109109
Assert.Null(form.Get("q4"));
110-
Assert.Equal("v5,v5", form.Get("Q5"));
110+
Assert.Equal("v5,v+5", form.Get("Q5"));
111111

112112
form = request.ReadFormAsync().Result;
113113
Assert.Equal("v1", form.Get("q1"));
114114
Assert.Equal("v2,b", form.Get("Q2"));
115115
Assert.Equal("v3,v4", form.Get("q3"));
116116
Assert.Null(form.Get("q4"));
117-
Assert.Equal("v5,v5", form.Get("Q5"));
117+
Assert.Equal("v5,v+5", form.Get("Q5"));
118118
}
119119
}
120120
}

tests/Microsoft.Owin.Tests/Microsoft.Owin.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<Compile Include="Builder\AppBuilderTestExtensions.cs" />
6464
<Compile Include="Builder\AppBuilderTests.cs" />
6565
<Compile Include="CookieChunkingTests.cs" />
66+
<Compile Include="RequestCookieTests.cs" />
6667
<Compile Include="FormsTests.cs" />
6768
<Compile Include="HeaderTests.cs" />
6869
<Compile Include="HostStringTests.cs" />
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Linq;
6+
using Xunit;
7+
using Xunit.Extensions;
8+
9+
namespace Microsoft.Owin.Tests
10+
{
11+
public class RequestCookieTests
12+
{
13+
[Theory]
14+
[InlineData("key=value", "key", "value")]
15+
[InlineData("__secure-key=value", "__secure-key", "value")]
16+
[InlineData("key%2C=%21value", "key,", "!value")]
17+
[InlineData("ke%23y%2C=val%5Eue", "ke#y,", "val^ue")]
18+
[InlineData("base64=QUI%2BREU%2FRw%3D%3D", "base64", "QUI+REU/Rw==")]
19+
[InlineData("base64=QUI+REU/Rw==", "base64", "QUI+REU/Rw==")]
20+
public void UnEscapesValues(string input, string expectedKey, string expectedValue)
21+
{
22+
var context = new OwinRequest();
23+
context.Headers["Cookie"] = input;
24+
var cookies = context.Cookies;
25+
26+
Assert.Equal(1, cookies.Count());
27+
Assert.Equal(Uri.EscapeDataString(expectedKey), cookies.Single().Key);
28+
Assert.Equal(expectedValue, cookies[expectedKey]);
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy