mirror of
https://github.com/Radarr/Radarr
synced 2026-01-18 13:33:20 +01:00
150 lines
4.3 KiB
C#
150 lines
4.3 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
|
|
|
|
using System;
|
|
using System.Text;
|
|
|
|
namespace Microsoft.AspNet.SignalR.Infrastructure
|
|
{
|
|
// Taken from System.Net.Http.Formatting.Internal.UrlDecoder.cs (http://aspnetwebstack.codeplex.com/)
|
|
|
|
/// <summary>
|
|
/// Helpers for decoding URI query components.
|
|
/// </summary>
|
|
internal static class UrlDecoder
|
|
{
|
|
// The implementation below is ported from WebUtility for use in .Net 4
|
|
|
|
public static string UrlDecode(string str)
|
|
{
|
|
if (str == null)
|
|
return null;
|
|
|
|
return UrlDecodeInternal(str, Encoding.UTF8);
|
|
}
|
|
|
|
#region UrlDecode implementation
|
|
|
|
private static string UrlDecodeInternal(string value, Encoding encoding)
|
|
{
|
|
if (value == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
int count = value.Length;
|
|
var helper = new DecoderHelper(count, encoding);
|
|
|
|
// go through the string's chars collapsing %XX and %uXXXX and
|
|
// appending each char as char, with exception of %XX constructs
|
|
// that are appended as bytes
|
|
|
|
for (int pos = 0; pos < count; pos++)
|
|
{
|
|
char ch = value[pos];
|
|
|
|
if (ch == '+')
|
|
{
|
|
ch = ' ';
|
|
}
|
|
else if (ch == '%' && pos < count - 2)
|
|
{
|
|
int h1 = HexToInt(value[pos + 1]);
|
|
int h2 = HexToInt(value[pos + 2]);
|
|
|
|
if (h1 >= 0 && h2 >= 0)
|
|
{ // valid 2 hex chars
|
|
byte b = (byte)((h1 << 4) | h2);
|
|
pos += 2;
|
|
|
|
// don't add as char
|
|
helper.AddByte(b);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((ch & 0xFF80) == 0)
|
|
helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode
|
|
else
|
|
helper.AddChar(ch);
|
|
}
|
|
|
|
return helper.GetString();
|
|
}
|
|
|
|
private static int HexToInt(char h)
|
|
{
|
|
return (h >= '0' && h <= '9') ? h - '0' :
|
|
(h >= 'a' && h <= 'f') ? h - 'a' + 10 :
|
|
(h >= 'A' && h <= 'F') ? h - 'A' + 10 :
|
|
-1;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DecoderHelper nested class
|
|
|
|
// Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either chars or bytes
|
|
private class DecoderHelper
|
|
{
|
|
private int _bufferSize;
|
|
|
|
// Accumulate characters in a special array
|
|
private int _numChars;
|
|
private char[] _charBuffer;
|
|
|
|
// Accumulate bytes for decoding into characters in a special array
|
|
private int _numBytes;
|
|
private byte[] _byteBuffer;
|
|
|
|
// Encoding to convert chars to bytes
|
|
private Encoding _encoding;
|
|
|
|
private void FlushBytes()
|
|
{
|
|
if (_numBytes > 0)
|
|
{
|
|
_numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars);
|
|
_numBytes = 0;
|
|
}
|
|
}
|
|
|
|
internal DecoderHelper(int bufferSize, Encoding encoding)
|
|
{
|
|
_bufferSize = bufferSize;
|
|
_encoding = encoding;
|
|
|
|
_charBuffer = new char[bufferSize];
|
|
// byte buffer created on demand
|
|
}
|
|
|
|
internal void AddChar(char ch)
|
|
{
|
|
if (_numBytes > 0)
|
|
FlushBytes();
|
|
|
|
_charBuffer[_numChars++] = ch;
|
|
}
|
|
|
|
internal void AddByte(byte b)
|
|
{
|
|
if (_byteBuffer == null)
|
|
_byteBuffer = new byte[_bufferSize];
|
|
|
|
_byteBuffer[_numBytes++] = b;
|
|
}
|
|
|
|
internal String GetString()
|
|
{
|
|
if (_numBytes > 0)
|
|
FlushBytes();
|
|
|
|
if (_numChars > 0)
|
|
return new String(_charBuffer, 0, _numChars);
|
|
else
|
|
return String.Empty;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|