377 строки
13 KiB
C#
377 строки
13 KiB
C#
//
|
|
// Copyright (c) .NET Foundation and Contributors
|
|
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// See LICENSE file in the project root for full license information.
|
|
//
|
|
// IMPORTANT: this file is used by nanoFramework.System.Net.Http, we place it here to allow the scenario of using an independent from hardware.
|
|
// So this is a duplicate file and any change from the original should be replicated here. It is a compromise to allow the scenario.
|
|
|
|
using System.Text;
|
|
|
|
namespace System.Web.Private
|
|
{
|
|
/// <summary>
|
|
/// Utilities to encode and decode URLs.
|
|
/// </summary>
|
|
internal class HttpUtility
|
|
{
|
|
/// <summary>
|
|
/// Encodes a URL string.
|
|
/// </summary>
|
|
/// <param name="str">The text to encode.</param>
|
|
/// <returns>An encoded string.</returns>
|
|
public static string UrlEncode(string str)
|
|
{
|
|
if ((str == null) || (str == string.Empty))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
return new string(Encoding.UTF8.GetChars(UrlEncodeToBytes(str, Encoding.UTF8)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Encodes a URL string using the specified encoding object.
|
|
/// </summary>
|
|
/// <param name="str">The text to encode.</param>
|
|
/// <param name="e">The <see cref="Encoding"/> object that specifies the encoding scheme.</param>
|
|
/// <returns>An encoded string.</returns>
|
|
public static string UrlEncode(
|
|
string str,
|
|
Encoding e)
|
|
{
|
|
if ((str == null) || (str == string.Empty))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
return new string(e.GetChars(UrlEncodeToBytes(str, e)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a byte array into a URL-encoded string, starting at the specified position in the array and continuing for the specified number of bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to encode.</param>
|
|
/// <param name="offset">The position in the byte array at which to begin encoding.</param>
|
|
/// <param name="count">The number of bytes to encode.</param>
|
|
/// <returns>An encoded string.</returns>
|
|
public static string UrlEncode(
|
|
byte[] bytes,
|
|
int offset,
|
|
int count)
|
|
{
|
|
return new string(Encoding.UTF8.GetChars(UrlEncodeBytesToBytesInternal(bytes, offset, count, false)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a byte array into an encoded URL string.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to encode.</param>
|
|
/// <returns>An encoded string.</returns>
|
|
public static string UrlEncode(byte[] bytes) => UrlEncode(bytes, 0, bytes.Length);
|
|
|
|
/// <summary>
|
|
/// Converts a string into a URL-encoded array of bytes using the specified encoding object.
|
|
/// </summary>
|
|
/// <param name="str">The string to encode.</param>
|
|
/// <param name="e">The <see cref="Encoding"/> that specifies the encoding scheme.</param>
|
|
/// <returns>An encoded array of bytes.</returns>
|
|
public static byte[] UrlEncodeToBytes(string str, Encoding e)
|
|
{
|
|
if (str == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var bytes = e.GetBytes(str);
|
|
|
|
return UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded array of bytes into a decoded array of bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to encode</param>
|
|
/// <returns>A decoded array of bytes.</returns>
|
|
public static byte[] UrlEncodeToBytes(byte[] bytes) => UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false);
|
|
|
|
/// <summary>
|
|
/// Converts an array of bytes into a URL-encoded array of bytes, starting at the specified position in the array and continuing for the specified number of bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to encode</param>
|
|
/// <param name="offset">The position in the byte array at which to begin encoding</param>
|
|
/// <param name="count">The number of bytes to encode</param>
|
|
/// <returns>An encoded array of bytes.</returns>
|
|
public static byte[] UrlEncodeToBytes(
|
|
byte[] bytes,
|
|
int offset,
|
|
int count) => UrlEncodeBytesToBytesInternal(
|
|
bytes,
|
|
offset,
|
|
count,
|
|
false);
|
|
|
|
private static byte[] UrlEncodeBytesToBytesInternal(
|
|
byte[] bytes,
|
|
int offset,
|
|
int count,
|
|
bool alwaysCreateReturnValue)
|
|
{
|
|
var num = 0;
|
|
var num2 = 0;
|
|
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var ch = (char)bytes[offset + i];
|
|
|
|
if (ch == ' ')
|
|
{
|
|
num++;
|
|
}
|
|
else if (!IsSafe(ch))
|
|
{
|
|
num2++;
|
|
}
|
|
}
|
|
if ((!alwaysCreateReturnValue && (num == 0))
|
|
&& (num2 == 0))
|
|
{
|
|
return bytes;
|
|
}
|
|
|
|
var buffer = new byte[count + (num2 * 2)];
|
|
var num4 = 0;
|
|
|
|
for (var j = 0; j < count; j++)
|
|
{
|
|
var num6 = bytes[offset + j];
|
|
var ch2 = (char)num6;
|
|
|
|
if (IsSafe(ch2))
|
|
{
|
|
buffer[num4++] = num6;
|
|
}
|
|
else if (ch2 == ' ')
|
|
{
|
|
buffer[num4++] = 0x2b;
|
|
}
|
|
else
|
|
{
|
|
buffer[num4++] = 0x25;
|
|
buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15);
|
|
buffer[num4++] = (byte)IntToHex(num6 & 15);
|
|
}
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
private static char IntToHex(int n)
|
|
{
|
|
if (n <= 9)
|
|
{
|
|
return (char)(n + 0x30);
|
|
}
|
|
|
|
return (char)((n - 10) + 0x41);
|
|
}
|
|
|
|
private static bool IsSafe(char ch)
|
|
{
|
|
if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')))
|
|
|| ((ch >= '0') && (ch <= '9')))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
switch (ch)
|
|
{
|
|
case '(':
|
|
case ')':
|
|
case '*':
|
|
case '-':
|
|
case '.':
|
|
case '_':
|
|
case '!':
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a string that has been encoded for transmission in a URL into a decoded string.
|
|
/// </summary>
|
|
/// <param name="str">The string to decode.</param>
|
|
/// <returns>The decoded URL</returns>
|
|
public static string UrlDecode(string str)
|
|
{
|
|
if (string.IsNullOrEmpty(str))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
var data = Encoding.UTF8.GetBytes(str);
|
|
|
|
return new string(Encoding.UTF8.GetChars(UrlDecodeToBytes(data, 0, data.Length)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded string into a decoded string, using the specified encoding object.
|
|
/// </summary>
|
|
/// <param name="str">The string to decode.</param>
|
|
/// <param name="e">The <see cref="Encoding"/> that specifies the decoding scheme.</param>
|
|
/// <returns>A decoded string.</returns>
|
|
public static string UrlDecode(string str, Encoding e)
|
|
{
|
|
if ((str == null) || (str == string.Empty))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
var data = e.GetBytes(str);
|
|
return new string(e.GetChars(UrlDecodeToBytes(data, 0, data.Length)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded byte array into a decoded string using the specified encoding object, starting at the specified position in the array, and continuing for the specified number of bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to decode.</param>
|
|
/// <param name="offset">The position in the byte to begin decoding</param>
|
|
/// <param name="count">The number of bytes to decode.</param>
|
|
/// <param name="e">The <see cref="Encoding"/> object that specifies the encoding scheme.</param>
|
|
/// <returns>A decoded string.</returns>
|
|
public static string UrlDecode(
|
|
byte[] bytes,
|
|
int offset,
|
|
int count,
|
|
Encoding e) => new(e.GetChars(UrlDecodeToBytes(
|
|
bytes,
|
|
offset,
|
|
count)));
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded byte array into a decoded string using the specified decoding object.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to decode.</param>
|
|
/// <param name="e">The <see cref="Encoding"/> object that specifies the encoding scheme.</param>
|
|
/// <returns>A decoded string.</returns>
|
|
public static string UrlDecode(
|
|
byte[] bytes,
|
|
Encoding e) => new string(e.GetChars(UrlDecodeToBytes(
|
|
bytes,
|
|
0,
|
|
bytes.Length)));
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded array of bytes into a decoded array of bytes, starting at the specified position in the array and continuing for the specified number of bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to decode.</param>
|
|
/// <param name="offset">The position in the byte array at which to begin decoding.</param>
|
|
/// <param name="count">The number of bytes to decode.</param>
|
|
/// <returns>A decoded array of bytes.</returns>
|
|
public static byte[] UrlDecodeToBytes(
|
|
byte[] bytes,
|
|
int offset,
|
|
int count)
|
|
{
|
|
var length = 0;
|
|
var sourceArray = new byte[count];
|
|
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var index = offset + i;
|
|
var num4 = bytes[index];
|
|
|
|
if (num4 == 0x2b)
|
|
{
|
|
num4 = 0x20;
|
|
}
|
|
else if ((num4 == 0x25)
|
|
&& (i < (count - 2)))
|
|
{
|
|
var num5 = HexToInt((char)bytes[index + 1]);
|
|
var num6 = HexToInt((char)bytes[index + 2]);
|
|
|
|
if ((num5 >= 0)
|
|
&& (num6 >= 0))
|
|
{
|
|
num4 = (byte)((num5 << 4) | num6);
|
|
i += 2;
|
|
}
|
|
}
|
|
sourceArray[length++] = num4;
|
|
}
|
|
|
|
if (length < sourceArray.Length)
|
|
{
|
|
var destinationArray = new byte[length];
|
|
Array.Copy(sourceArray, destinationArray, length);
|
|
sourceArray = destinationArray;
|
|
}
|
|
|
|
return sourceArray;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded string into a decoded array of bytes using the specified decoding object.
|
|
/// </summary>
|
|
/// <param name="str">The string to encode.</param>
|
|
/// <param name="e">The <see cref="Encoding"/> object that specifies the encoding scheme.</param>
|
|
/// <returns>A decoded array of bytes.</returns>
|
|
public static byte[] UrlDecodeToBytes(
|
|
string str,
|
|
Encoding e)
|
|
{
|
|
var data = e.GetBytes(str);
|
|
return UrlDecodeToBytes(data, 0, data.Length);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded string into a decoded array of bytes.
|
|
/// </summary>
|
|
/// <param name="str">The string to decode.</param>
|
|
/// <returns>A decoded array of bytes.</returns>
|
|
public static byte[] UrlDecodeToBytes(string str) => UrlDecodeToBytes(
|
|
str,
|
|
Encoding.UTF8);
|
|
|
|
/// <summary>
|
|
/// Converts a URL-encoded array of bytes into a decoded array of bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The array of bytes to decode.</param>
|
|
/// <returns>A decoded array of bytes.</returns>
|
|
public static byte[] UrlDecodeToBytes(byte[] bytes) => UrlDecodeToBytes(
|
|
bytes,
|
|
0,
|
|
bytes.Length);
|
|
|
|
/// <summary>
|
|
/// Get the int value of a char.
|
|
/// </summary>
|
|
/// <param name="h">The <see cref="char"/> to convert.</param>
|
|
/// <returns>The <see cref="int"/> value of the <see cref="char"/>.</returns>
|
|
public static int HexToInt(char h)
|
|
{
|
|
if ((h >= '0') &&
|
|
(h <= '9'))
|
|
{
|
|
return (h - '0');
|
|
}
|
|
|
|
if ((h >= 'a') &&
|
|
(h <= 'f'))
|
|
{
|
|
return ((h - 'a') + 10);
|
|
}
|
|
|
|
if ((h >= 'A') &&
|
|
(h <= 'F'))
|
|
{
|
|
return ((h - 'A') + 10);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
}
|