Exemple #1
0
        private string GetDecodedString(ReadOnlySpan <byte> readOnlySpan)
        {
            if (readOnlySpan.Length == 0)
            {
                return(string.Empty);
            }
            else if (_encoding == Encoding.UTF8 || _encoding == Encoding.ASCII)
            {
                // UrlDecoder only works on UTF8 (and implicitly ASCII)

                // We need to create a Span from a ReadOnlySpan. This cast is safe because the memory is still held by the pipe
                // We will also create a string from it by the end of the function.
                var span = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(readOnlySpan[0]), readOnlySpan.Length);

                var bytes = UrlDecoder.DecodeInPlace(span, isFormEncoding: true);
                span = span.Slice(0, bytes);

                return(_encoding.GetString(span));
            }
            else
            {
                // Slow path for Unicode and other encodings.
                // Just do raw string replacement.
                var decodedString = _encoding.GetString(readOnlySpan);
                decodedString = decodedString.Replace('+', ' ');
                return(Uri.UnescapeDataString(decodedString));
            }
        }
Exemple #2
0
    [InlineData("%ED%A0%81")]    // Invalid range 0xD800-0xDFFF
    public void ByteOutOfUtf8RangeDecodeInPlaceLeavesUnencoded(string input)
    {
        var source = Encoding.UTF8.GetBytes(input.ToCharArray());
        var length = UrlDecoder.DecodeInPlace(source.AsSpan(), true);

        Assert.Equal(source.Length, length);
        Assert.True(source.AsSpan(0, length).SequenceEqual(Encoding.UTF8.GetBytes(input).AsSpan()));
    }
Exemple #3
0
    [InlineData("%ED%A0%81")]    // Invalid range 0xD800-0xDFFF
    public void StringOutOfUtf8RangeDecodeInPlaceLeavesUnencoded(string input)
    {
        var source = input.ToCharArray();
        var length = UrlDecoder.DecodeInPlace(source.AsSpan());

        Assert.Equal(input.Length, length);
        Assert.True(source.AsSpan(0, length).SequenceEqual(input.AsSpan()));
    }
Exemple #4
0
    public void ByteFormsEncodingDecodeInPlaceDecodesPercent2F(string input)
    {
        var source = Encoding.UTF8.GetBytes(input.ToCharArray());
        var length = UrlDecoder.DecodeInPlace(source.AsSpan(), true);

        Assert.Equal(1, length);
        Assert.True(source.AsSpan(0, length).SequenceEqual(Encoding.UTF8.GetBytes("/").AsSpan()));
    }
Exemple #5
0
    public void ByteDecodeInPlace(byte[] input, byte[] expected)
    {
        var destination = new byte[input.Length];

        input.AsSpan().CopyTo(destination);
        int length = UrlDecoder.DecodeInPlace(destination.AsSpan(), false);

        Assert.True(destination.AsSpan(0, length).SequenceEqual(expected.AsSpan()));
    }
Exemple #6
0
    public void StringDecodeInPlace(string input, string expected)
    {
        var destination = new char[input.Length];

        input.CopyTo(destination);
        int length = UrlDecoder.DecodeInPlace(destination.AsSpan());

        Assert.True(destination.AsSpan(0, length).SequenceEqual(expected.AsSpan()));
    }
        public static string DecodePath(Span <byte> path, bool pathEncoded, string rawTarget, int queryLength)
        {
            int pathLength;

            if (pathEncoded)
            {
                // URI was encoded, unescape and then parse as UTF-8
                // Disabling warning temporary
                pathLength = UrlDecoder.DecodeInPlace(path);

                // Removing dot segments must be done after unescaping. From RFC 3986:
                //
                // URI producing applications should percent-encode data octets that
                // correspond to characters in the reserved set unless these characters
                // are specifically allowed by the URI scheme to represent data in that
                // component.  If a reserved character is found in a URI component and
                // no delimiting role is known for that character, then it must be
                // interpreted as representing the data octet corresponding to that
                // character's encoding in US-ASCII.
                //
                // https://tools.ietf.org/html/rfc3986#section-2.2
                pathLength = RemoveDotSegments(path.Slice(0, pathLength));

                return(GetUtf8String(path.Slice(0, pathLength)));
            }

            pathLength = RemoveDotSegments(path);

            if (path.Length == pathLength && queryLength == 0)
            {
                // If no decoding was required, no dot segments were removed and
                // there is no query, the request path is the same as the raw target
                return(rawTarget);
            }

            return(path.Slice(0, pathLength).GetAsciiStringNonNullCharacters());
        }
Exemple #8
0
    public void StringInputNullCharDecodeInPlaceThrows()
    {
        var source = "%00".ToCharArray();

        Assert.Throws <InvalidOperationException>(() => UrlDecoder.DecodeInPlace(source.AsSpan()));
    }
Exemple #9
0
    public void ByteInputNullCharDecodeInPlaceThrows()
    {
        var source = Encoding.UTF8.GetBytes("%00");

        Assert.Throws <InvalidOperationException>(() => UrlDecoder.DecodeInPlace(source.AsSpan(), false));
    }