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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Xml;
using Newtonsoft.Json.Linq;
namespace System.Net.Http
{
/// <summary>
/// Provides various internal utility functions
/// </summary>
internal static class FormattingUtilities
{
// Supported date formats for input.
private static readonly string[] dateFormats = new string[]
{
// "r", // RFC 1123, required output format but too strict for input
"ddd, d MMM yyyy H:m:s 'GMT'", // RFC 1123 (r, except it allows both 1 and 01 for date and time)
"ddd, d MMM yyyy H:m:s", // RFC 1123, no zone - assume GMT
"d MMM yyyy H:m:s 'GMT'", // RFC 1123, no day-of-week
"d MMM yyyy H:m:s", // RFC 1123, no day-of-week, no zone
"ddd, d MMM yy H:m:s 'GMT'", // RFC 1123, short year
"ddd, d MMM yy H:m:s", // RFC 1123, short year, no zone
"d MMM yy H:m:s 'GMT'", // RFC 1123, no day-of-week, short year
"d MMM yy H:m:s", // RFC 1123, no day-of-week, short year, no zone
"dddd, d'-'MMM'-'yy H:m:s 'GMT'", // RFC 850
"dddd, d'-'MMM'-'yy H:m:s", // RFC 850 no zone
"ddd MMM d H:m:s yyyy", // ANSI C's asctime() format
"ddd, d MMM yyyy H:m:s zzz", // RFC 5322
"ddd, d MMM yyyy H:m:s", // RFC 5322 no zone
"d MMM yyyy H:m:s zzz", // RFC 5322 no day-of-week
"d MMM yyyy H:m:s", // RFC 5322 no day-of-week, no zone
};
// Valid header token characters are within the range 0x20 < c < 0x7F excluding the following characters
private const string NonTokenChars = "()<>@,;:\\\"/[]?={}";
/// <summary>
/// The default max depth for our formatter is 256
/// </summary>
public const int DefaultMaxDepth = 256;
/// <summary>
/// The default min depth for our formatter is 1
/// </summary>
public const int DefaultMinDepth = 1;
/// <summary>
/// HTTP X-Requested-With header field name
/// </summary>
public const string HttpRequestedWithHeader = @"x-requested-with";
/// <summary>
/// HTTP X-Requested-With header field value
/// </summary>
public const string HttpRequestedWithHeaderValue = @"xmlhttprequest";
/// <summary>
/// HTTP Host header field name
/// </summary>
public const string HttpHostHeader = "Host";
/// <summary>
/// HTTP Version token
/// </summary>
public const string HttpVersionToken = "HTTP";
/// <summary>
/// A <see cref="Type"/> representing <see cref="UTF8Encoding"/>.
/// </summary>
public static readonly Type Utf8EncodingType = typeof(UTF8Encoding);
/// <summary>
/// A <see cref="Type"/> representing <see cref="UnicodeEncoding"/>.
/// </summary>
public static readonly Type Utf16EncodingType = typeof(UnicodeEncoding);
/// <summary>
/// A <see cref="Type"/> representing <see cref="HttpRequestMessage"/>.
/// </summary>
public static readonly Type HttpRequestMessageType = typeof(HttpRequestMessage);
/// <summary>
/// A <see cref="Type"/> representing <see cref="HttpResponseMessage"/>.
/// </summary>
public static readonly Type HttpResponseMessageType = typeof(HttpResponseMessage);
/// <summary>
/// A <see cref="Type"/> representing <see cref="HttpContent"/>.
/// </summary>
public static readonly Type HttpContentType = typeof(HttpContent);
/// <summary>
/// A <see cref="Type"/> representing <see cref="DelegatingEnumerable{T}"/>.
/// </summary>
public static readonly Type DelegatingEnumerableGenericType = typeof(DelegatingEnumerable<>);
/// <summary>
/// A <see cref="Type"/> representing <see cref="IEnumerable{T}"/>.
/// </summary>
public static readonly Type EnumerableInterfaceGenericType = typeof(IEnumerable<>);
/// <summary>
/// A <see cref="Type"/> representing <see cref="IQueryable{T}"/>.
/// </summary>
public static readonly Type QueryableInterfaceGenericType = typeof(IQueryable<>);
/// <summary>
/// Determines whether <paramref name="type"/> is a <see cref="JToken"/> type.
/// </summary>
/// <param name="type">The type to test.</param>
/// <returns>
/// <c>true</c> if <paramref name="type"/> is a <see cref="JToken"/> type; otherwise, <c>false</c>.
/// </returns>
public static bool IsJTokenType(Type type)
{
return typeof(JToken).IsAssignableFrom(type);
}
/// <summary>
/// Creates an empty <see cref="HttpContentHeaders"/> instance. The only way is to get it from a dummy
/// <see cref="HttpContent"/> instance.
/// </summary>
/// <returns>The created instance.</returns>
public static HttpContentHeaders CreateEmptyContentHeaders()
{
HttpContent tempContent = null;
HttpContentHeaders contentHeaders = null;
try
{
tempContent = new StringContent(String.Empty);
contentHeaders = tempContent.Headers;
contentHeaders.Clear();
}
finally
{
// We can dispose the content without touching the headers
if (tempContent != null)
{
tempContent.Dispose();
}
}
return contentHeaders;
}
/// <summary>
/// Ensure the actual collection is identical to the expected one
/// </summary>
/// <param name="actual">The actual collection of the instance</param>
/// <param name="expected">The expected collection of the instance</param>
/// <returns>Returns true if they are identical</returns>
public static bool ValidateCollection(Collection<MediaTypeHeaderValue> actual, MediaTypeHeaderValue[] expected)
{
if (actual.Count != expected.Length)
{
return false;
}
foreach (MediaTypeHeaderValue value in expected)
{
if (!actual.Contains(value))
{
return false;
}
}
return true;
}
/// <summary>
/// Create a default reader quotas with a default depth quota of 1K
/// </summary>
/// <returns></returns>
public static XmlDictionaryReaderQuotas CreateDefaultReaderQuotas()
{
return new XmlDictionaryReaderQuotas()
{
MaxArrayLength = Int32.MaxValue,
MaxBytesPerRead = Int32.MaxValue,
MaxDepth = DefaultMaxDepth,
MaxNameTableCharCount = Int32.MaxValue,
MaxStringContentLength = Int32.MaxValue
};
}
/// <summary>
/// Remove bounding quotes on a token if present
/// </summary>
/// <param name="token">Token to unquote.</param>
/// <returns>Unquoted token.</returns>
public static string UnquoteToken(string token)
{
if (String.IsNullOrWhiteSpace(token))
{
return token;
}
if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
{
return token.Substring(1, token.Length - 2);
}
return token;
}
public static bool ValidateHeaderToken(string token)
{
return token != null && !token.Any(c => c < 0x21 || c > 0x7E || NonTokenChars.IndexOf(c) != -1);
}
public static string DateToString(DateTimeOffset dateTime)
{
// Format according to RFC1123; 'r' uses invariant info (DateTimeFormatInfo.InvariantInfo)
return dateTime.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture);
}
public static bool TryParseDate(string input, out DateTimeOffset result)
{
return DateTimeOffset.TryParseExact(input, dateFormats, DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeUniversal,
out result);
}
/// <summary>
/// Parses valid integer strings with no leading signs, whitespace or other <see cref="NumberStyles"/>
/// </summary>
/// <param name="value">The value to parse</param>
/// <param name="result">The result</param>
/// <returns>True if value was valid; false otherwise.</returns>
public static bool TryParseInt32(string value, out int result)
{
return Int32.TryParse(value, NumberStyles.None, NumberFormatInfo.InvariantInfo, out result);
}
}
}
|