Skip to content

Commit 8d170ac

Browse files
authored
Adding HttpUtility for URL Encode and Decode (#144)
1 parent 7894108 commit 8d170ac

4 files changed

Lines changed: 327 additions & 1 deletion

File tree

nanoFramework.System.Net.Http-client/System.Net.Http-client.nfproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@
134134
<Compile Include="..\nanoFramework.System.Net.Http\Properties\AssemblyInfo.cs">
135135
<Link>Properties\AssemblyInfo.cs</Link>
136136
</Compile>
137+
<Compile Include="..\nanoFramework.System.Net.Http\Http\System.Net.HttpUtility.cs">
138+
<Link>Http\System.Net.HttpUtility.cs</Link>
139+
</Compile>
137140
</ItemGroup>
138141
<ItemGroup>
139142
<None Include="..\nanoFramework.System.Net.Http\key.snk" />

nanoFramework.System.Net.Http-server/System.Net.Http-server.nfproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@
128128
</Compile>
129129
<Compile Include="..\nanoFramework.System.Net.Http\Properties\AssemblyInfo.cs">
130130
<Link>Properties\AssemblyInfo.cs</Link>
131+
</Compile>
132+
<Compile Include="..\nanoFramework.System.Net.Http\Http\System.Net.HttpUtility.cs">
133+
<Link>Http\System.Net.HttpUtility.cs</Link>
131134
</Compile>
132135
</ItemGroup>
133136
<ItemGroup>
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
4+
// See LICENSE file in the project root for full license information.
5+
//
6+
7+
using System;
8+
using System.Text;
9+
10+
namespace System.Web
11+
{
12+
/// <summary>
13+
/// Utilities to encode and decode url
14+
/// </summary>
15+
public class HttpUtility
16+
{
17+
/// <summary>
18+
/// Encode an URL using UTF8
19+
/// </summary>
20+
/// <param name="str">The URL string to encode</param>
21+
/// <returns>The encoded string URL</returns>
22+
public static string UrlEncode(string str)
23+
{
24+
if ((str == null) || (str == string.Empty))
25+
{
26+
return string.Empty;
27+
}
28+
29+
return new string(Encoding.UTF8.GetChars(UrlEncodeToBytes(str, Encoding.UTF8)));
30+
}
31+
32+
/// <summary>
33+
/// Encode an URL
34+
/// </summary>
35+
/// <param name="str">The URL string to encode</param>
36+
/// <param name="e">The Encoding object that specifies the encoding scheme</param>
37+
/// <returns>The encoded string URL</returns>
38+
public static string UrlEncode(string str, Encoding e)
39+
{
40+
if ((str == null) || (str == string.Empty))
41+
{
42+
return string.Empty;
43+
}
44+
45+
return new string(e.GetChars(UrlEncodeToBytes(str, e)));
46+
}
47+
48+
/// <summary>
49+
/// Encode an URL
50+
/// </summary>
51+
/// <param name="bytes">The array of bytes to encode</param>
52+
/// <param name="offset">The position in the byte array at which to begin encoding</param>
53+
/// <param name="count">The number of bytes to encode</param>
54+
/// <returns>The encoded string URL</returns>
55+
public static string UrlEncode(byte[] bytes, int offset, int count)
56+
{
57+
return new string(Encoding.UTF8.GetChars(UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false)));
58+
}
59+
60+
/// <summary>
61+
/// Encode an URL
62+
/// </summary>
63+
/// <param name="bytes">The array of bytes to encode</param>
64+
/// <returns>The encoded string URLL</returns>
65+
public static string UrlEncode(byte[] bytes) => UrlEncode(bytes, 0, bytes.Length);
66+
67+
/// <summary>
68+
/// Encode an URL into a byte array
69+
/// </summary>
70+
/// <param name="str">The URL string to encode</param>
71+
/// <param name="e"></param>
72+
/// <returns>The encoded byte array</returns>
73+
public static byte[] UrlEncodeToBytes(string str, Encoding e)
74+
{
75+
if (str == null)
76+
{
77+
return null;
78+
}
79+
var bytes = e.GetBytes(str);
80+
return UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false);
81+
}
82+
83+
/// <summary>
84+
/// Encode a byte array URL into a byte array
85+
/// </summary>
86+
/// <param name="bytes">The array of bytes to encode</param>
87+
/// <returns>The encoded byte array</returns>
88+
public static byte[] UrlEncodeToBytes(byte[] bytes) => UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false);
89+
90+
/// <summary>
91+
/// Encode a byte array URL into a byte array
92+
/// </summary>
93+
/// <param name="bytes">The array of bytes to encode</param>
94+
/// <param name="offset">The position in the byte array at which to begin encoding</param>
95+
/// <param name="count">The number of bytes to encode</param>
96+
/// <returns>The encoded byte array</returns>
97+
public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) => UrlEncodeBytesToBytesInternal(bytes, offset, count, false);
98+
99+
private static byte[] UrlEncodeBytesToBytesInternal(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue)
100+
{
101+
var num = 0;
102+
var num2 = 0;
103+
for (var i = 0; i < count; i++)
104+
{
105+
var ch = (char)bytes[offset + i];
106+
if (ch == ' ')
107+
{
108+
num++;
109+
}
110+
else if (!IsSafe(ch))
111+
{
112+
num2++;
113+
}
114+
}
115+
if ((!alwaysCreateReturnValue && (num == 0)) &&
116+
(num2 == 0))
117+
{
118+
return bytes;
119+
}
120+
var buffer = new byte[count + (num2 * 2)];
121+
var num4 = 0;
122+
for (var j = 0; j < count; j++)
123+
{
124+
var num6 = bytes[offset + j];
125+
var ch2 = (char)num6;
126+
if (IsSafe(ch2))
127+
{
128+
buffer[num4++] = num6;
129+
}
130+
else if (ch2 == ' ')
131+
{
132+
buffer[num4++] = 0x2b;
133+
}
134+
else
135+
{
136+
buffer[num4++] = 0x25;
137+
buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15);
138+
buffer[num4++] = (byte)IntToHex(num6 & 15);
139+
}
140+
}
141+
return buffer;
142+
}
143+
144+
private static char IntToHex(int n)
145+
{
146+
if (n <= 9)
147+
{
148+
return (char)(n + 0x30);
149+
}
150+
return (char)((n - 10) + 0x61);
151+
}
152+
153+
private static bool IsSafe(char ch)
154+
{
155+
if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) ||
156+
((ch >= '0') && (ch <= '9')))
157+
{
158+
return true;
159+
}
160+
switch (ch)
161+
{
162+
case '\'':
163+
case '(':
164+
case ')':
165+
case '*':
166+
case '-':
167+
case '.':
168+
case '_':
169+
case '!':
170+
return true;
171+
}
172+
return false;
173+
}
174+
175+
/// <summary>
176+
/// Decode an UTF8 encoded URL
177+
/// </summary>
178+
/// <param name="url">The encoded URL</param>
179+
/// <returns>The decoded URL</returns>
180+
public static string UrlDecode(string url)
181+
{
182+
if ((url == null) || (url == string.Empty))
183+
{
184+
return string.Empty;
185+
}
186+
187+
var data = Encoding.UTF8.GetBytes(url);
188+
return new string(Encoding.UTF8.GetChars(UrlDecodeToBytes(data, 0, data.Length)));
189+
}
190+
191+
/// <summary>
192+
/// Decode an URL using the specified encoding
193+
/// </summary>
194+
/// <param name="str">The string to encode</param>
195+
/// <param name="e">The Encoding object that specifies the encoding scheme</param>
196+
/// <returns>The encoded string</returns>
197+
public static string UrlDecode(string str, Encoding e)
198+
{
199+
if ((str == null) || (str == string.Empty))
200+
{
201+
return string.Empty;
202+
}
203+
204+
var data = e.GetBytes(str);
205+
return new string(e.GetChars(UrlDecodeToBytes(data, 0, data.Length)));
206+
}
207+
208+
/// <summary>
209+
/// Decode an encoded URL
210+
/// </summary>
211+
/// <param name="bytes">The array of bytes to decode</param>
212+
/// <param name="offset">The position in the byte to begin decoding</param>
213+
/// <param name="count">The number of bytes to decode</param>
214+
/// <param name="e">The Encoding object that specifies the encoding scheme</param>
215+
/// <returns>The decoded URL</returns>
216+
public static string UrlDecode(byte[] bytes, int offset, int count, System.Text.Encoding e) => new string(e.GetChars(UrlDecodeToBytes(bytes, 0, bytes.Length)));
217+
218+
/// <summary>
219+
/// Decode an encoded URL
220+
/// </summary>
221+
/// <param name="bytes">The array of bytes to decode</param>
222+
/// <param name="e">The Encoding object that specifies the encoding scheme</param>
223+
/// <returns>The decoded URL</returns>
224+
public static string UrlDecode(byte[] bytes, System.Text.Encoding e) => new string(e.GetChars(UrlDecodeToBytes(bytes, 0, bytes.Length)));
225+
226+
/// <summary>
227+
/// Decode bytes array to byte array
228+
/// </summary>
229+
/// <param name="bytes">The array of bytes to decode</param>
230+
/// <param name="offset">The position in the byte array at which to begin decoding</param>
231+
/// <param name="count">The number of bytes to decode</param>
232+
/// <returns></returns>
233+
public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count)
234+
{
235+
var length = 0;
236+
var sourceArray = new byte[count];
237+
for (var i = 0; i < count; i++)
238+
{
239+
var index = offset + i;
240+
var num4 = bytes[index];
241+
if (num4 == 0x2b)
242+
{
243+
num4 = 0x20;
244+
}
245+
else if ((num4 == 0x25) &&
246+
(i < (count - 2)))
247+
{
248+
var num5 = HexToInt((char)bytes[index + 1]);
249+
var num6 = HexToInt((char)bytes[index + 2]);
250+
if ((num5 >= 0) &&
251+
(num6 >= 0))
252+
{
253+
num4 = (byte)((num5 << 4) | num6);
254+
i += 2;
255+
}
256+
}
257+
sourceArray[length++] = num4;
258+
}
259+
if (length < sourceArray.Length)
260+
{
261+
var destinationArray = new byte[length];
262+
Array.Copy(sourceArray, destinationArray, length);
263+
sourceArray = destinationArray;
264+
}
265+
return sourceArray;
266+
}
267+
268+
/// <summary>
269+
/// Decode bytes array to byte array
270+
/// </summary>
271+
/// <param name="str">The string to encode</param>
272+
/// <param name="e">The Encoding object that specifies the encoding scheme</param>
273+
/// <returns></returns>
274+
public static byte[] UrlDecodeToBytes(string str, System.Text.Encoding e)
275+
{
276+
var data = e.GetBytes(str);
277+
return UrlDecodeToBytes(data, 0, data.Length);
278+
}
279+
280+
/// <summary>
281+
/// Decode bytes array to byte array in UTF8
282+
/// </summary>
283+
/// <param name="str">The string to encode</param>
284+
/// <returns></returns>
285+
public static byte[] UrlDecodeToBytes(string str) => UrlDecodeToBytes(str, Encoding.UTF8);
286+
287+
/// <summary>
288+
/// Decode bytes array to byte array
289+
/// </summary>
290+
/// <param name="bytes">The array of bytes to decode</param>
291+
/// <returns></returns>
292+
public static byte[] UrlDecodeToBytes(byte[] bytes) => UrlDecodeToBytes(bytes, 0, bytes.Length);
293+
294+
/// <summary>
295+
/// Get the int value of a char
296+
/// </summary>
297+
/// <param name="h">a char</param>
298+
/// <returns>The int value of the char</returns>
299+
public static int HexToInt(char h)
300+
{
301+
if ((h >= '0') &&
302+
(h <= '9'))
303+
{
304+
return (h - '0');
305+
}
306+
if ((h >= 'a') &&
307+
(h <= 'f'))
308+
{
309+
return ((h - 'a') + 10);
310+
}
311+
if ((h >= 'A') &&
312+
(h <= 'F'))
313+
{
314+
return ((h - 'A') + 10);
315+
}
316+
return -1;
317+
}
318+
}
319+
}

nanoFramework.System.Net.Http/System.Net.Http.nfproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
<Compile Include="Properties\AssemblyInfo.cs" />
8989
</ItemGroup>
9090
<ItemGroup>
91+
<None Include="Http\System.Net.HttpUtility.cs" />
9192
<None Include="key.snk" />
9293
<None Include="packages.config" />
9394
</ItemGroup>
@@ -126,4 +127,4 @@
126127
</PropertyGroup>
127128
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets'))" />
128129
</Target>
129-
</Project>
130+
</Project>

0 commit comments

Comments
 (0)