-
Notifications
You must be signed in to change notification settings - Fork 4
/
HttpUtil.cs
204 lines (169 loc) · 6.49 KB
/
HttpUtil.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
namespace RenRen.Plurk
{
/// <summary>
/// Contains helper HTTP methods not available in System.Net namespace.
/// </summary>
public static class HttpUtility
{
#region "Public Methods"
/// <summary>
/// Parse an encoded query string using UTF8 encoding.
/// </summary>
/// <param name="s">The query string to parse.</param>
public static NameValueCollection ParseQueryString(String s)
{
return ParseQueryString(s, true, Encoding.UTF8);
}
/// <summary>
/// Parse a query string into a NameValueCollection using specified encoding settings.
/// </summary>
/// <param name="s">The query string to parse.</param>
/// <param name="urlencoded">Whether query string keys and values are URL encoded.</param>
/// <param name="encoding">The encoding to use.</param>
public static NameValueCollection ParseQueryString(String s, bool urlencoded, Encoding encoding)
{
NameValueCollection result = new NameValueCollection();
int l = (s != null) ? s.Length : 0;
int i = 0;
while (i < l) {
int si = i; // Next '&'
int ti = -1; // Next '='
while (i < l)
{
char cur = s[i];
if (cur == '=') {
if (ti < 0)
ti = i;
} else
if (cur == '&') break;
i++;
}
string name = null, value = null;
if (ti >= 0) {
name = s.Substring(si, ti - si);
value = s.Substring(ti + 1, i - ti - 1);
} else {
value = s.Substring(si, i - si);
}
if (urlencoded)
result.Add(UrlDecode(name, encoding), UrlDecode(value, encoding));
else
result.Add(name, value);
// trailing '&'
if (i == l - 1 && s[i] == '&')
result.Add(null, String.Empty);
i++;
}
return result;
}
/// <summary>
/// Decode an URL transmission-encoded string into its original representation using UTF8 encoding.
/// </summary>
/// <param name="s">The string to decode.</param>
public static string UrlDecode(string s)
{
return UrlDecode(s, Encoding.UTF8);
}
/// <summary>
/// Decode an URL transmission-encoded string into its original representation using specified encoding.
/// </summary>
/// <param name="s">The string to decode.</param>
/// <param name="encoding">The encoding to use.</param>
public static string UrlDecode(string s, Encoding encoding)
{
if (s == null) return null;
int count = s.Length;
UrlDecoder buffer = new UrlDecoder(count, encoding);
for (int pos = 0; pos < count; pos++) {
char ch = s[pos];
if (ch == '+') ch = ' ';
else
if ((ch == '%') && (pos < count - 2)) {
if ((s[pos + 1] == 'u') && pos < (count - 5)) { // %uXXXX
int h1 = HexToInt(s[pos + 2]);
int h2 = HexToInt(s[pos + 3]);
int h3 = HexToInt(s[pos + 4]);
int h4 = HexToInt(s[pos + 5]);
if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0) {
ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4);
pos += 5;
buffer.AddChar(ch); continue;
}
}
else { // %XX
int h1 = HexToInt(s[pos + 1]);
int h2 = HexToInt(s[pos + 2]);
if (h1 >= 0 && h2 >= 0) {
byte b = (byte)((h1 << 4) | h2);
pos += 2;
buffer.AddByte(b); continue;
}
}
}
if ((ch & 0xFF80) == 0)
buffer.AddByte((byte)ch);
else
buffer.AddChar(ch);
}
return buffer.GetString();
}
#endregion
#region "Private Helpers"
/// <summary>
/// Convert a hex character to its integer representation,
/// </summary>
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;
}
/// <summary>
/// Helper class to queue characters and buffers to be encoded.
/// </summary>
private class UrlDecoder
{
private int _bufferSize;
private int _charCount;
private char[] _charBuffer;
private int _byteCount;
private byte[] _byteBuffer;
private Encoding _encoding;
internal UrlDecoder(int bufferSize, Encoding encoding)
{
_bufferSize = bufferSize;
_encoding = encoding;
_charBuffer = new char[bufferSize];
// _byteByffer creates on demand
}
internal void AddChar(char ch)
{
if (_byteCount > 0) FlushBytes();
_charBuffer[_charCount++] = ch;
}
internal void AddByte(byte b)
{
if (_byteBuffer == null) _byteBuffer = new byte[_bufferSize];
_byteBuffer[_byteCount++] = b;
}
internal String GetString()
{
if (_byteCount > 0) FlushBytes();
return (_charCount > 0) ? (new String(_charBuffer, 0, _charCount)) : String.Empty;
}
private void FlushBytes()
{
if (_byteCount > 0) {
_charCount += _encoding.GetChars(_byteBuffer, 0, _byteCount, _charBuffer, _charCount);
_byteCount = 0;
}
}
}
#endregion
}
}