private static string UrlDecodeInternal(string value, Encoding encoding)
{
if (string.IsNullOrEmpty(value))
{
return value;
}
int count = value.Length;
UrlDecoder helper = new UrlDecoder(count, encoding);
// go through the string's chars collapsing %XX and
// appending each char as char, with exception of %XX constructs
// that are appended as bytes
bool needsDecodingUnsafe = false;
bool needsDecodingSpaces = false;
for (int pos = 0; pos < count; pos++)
{
char ch = value[pos];
if (ch == '+')
{
needsDecodingSpaces = true;
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);
needsDecodingUnsafe = true;
continue;
}
}
if ((ch & 0xFF80) == 0)
helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode
else
helper.AddChar(ch);
}
if (!needsDecodingUnsafe)
{
if (needsDecodingSpaces)
{
// Only spaces to decode
return value.Replace('+', ' ');
}
// Nothing to decode
return value;
}
return helper.GetString();
}