summaryrefslogtreecommitdiff
path: root/mcs/class/System.Net.Http
diff options
context:
space:
mode:
authorJo Shields <directhex@apebox.org>2014-02-19 22:12:43 +0000
committerJo Shields <directhex@apebox.org>2014-02-19 22:12:43 +0000
commit9972bf87b4f27d9c8f358ef8414ac1ab957a2f0f (patch)
tree5bb230c1d698659115f918e243c1d4b0aa4c7f51 /mcs/class/System.Net.Http
parentd0a215f5626219ff7927f576588a777e5331c7be (diff)
downloadmono-upstream/3.2.8+dfsg.tar.gz
Imported Upstream version 3.2.8+dfsgupstream/3.2.8+dfsg
Diffstat (limited to 'mcs/class/System.Net.Http')
-rw-r--r--mcs/class/System.Net.Http/Makefile2
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/AuthenticationHeaderValue.cs26
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/CollectionParser.cs117
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs2
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/EntityTagHeaderValue.cs37
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs45
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs56
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs2
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeHeaderValue.cs37
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs37
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueHeaderValue.cs89
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs53
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/Parser.cs10
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/ProductHeaderValue.cs31
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/ProductInfoHeaderValue.cs10
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/StringWithQualityHeaderValue.cs23
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingHeaderValue.cs28
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs36
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/ViaHeaderValue.cs25
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.Headers/WarningHeaderValue.cs25
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http.dll.sources1
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs9
-rw-r--r--mcs/class/System.Net.Http/System.Net.Http/StreamContent.cs16
-rw-r--r--mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeadersTest.cs8
-rw-r--r--mcs/class/System.Net.Http/Test/System.Net.Http.Headers/NameValueHeaderValueTest.cs3
-rw-r--r--mcs/class/System.Net.Http/Test/System.Net.Http/HttpRequestMessageTest.cs47
-rw-r--r--mcs/class/System.Net.Http/Test/System.Net.Http/HttpResponseMessageTest.cs50
-rw-r--r--mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs15
-rw-r--r--mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources53
29 files changed, 706 insertions, 187 deletions
diff --git a/mcs/class/System.Net.Http/Makefile b/mcs/class/System.Net.Http/Makefile
index 715fa63120..ce2e097fee 100644
--- a/mcs/class/System.Net.Http/Makefile
+++ b/mcs/class/System.Net.Http/Makefile
@@ -4,7 +4,7 @@ include ../../build/rules.make
LIBRARY = System.Net.Http.dll
-LIB_MCS_FLAGS = -r:System.Core.dll -r:System.dll
+LIB_MCS_FLAGS = -r:System.Core.dll -r:System.dll $(EXTRA_LIB_MCS_FLAGS)
TEST_MCS_FLAGS = -r:System.dll -r:System.Core.dll
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/AuthenticationHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/AuthenticationHeaderValue.cs
index 33f87db8f0..7bb2496a94 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/AuthenticationHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/AuthenticationHeaderValue.cs
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public class AuthenticationHeaderValue : ICloneable
@@ -85,8 +87,23 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out AuthenticationHeaderValue parsedValue)
{
var lexer = new Lexer (input);
- var t = lexer.Scan ();
- if (t != Token.Type.Token || !(lexer.PeekChar () == ' ' || lexer.PeekChar () == -1)) {
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
+ parsedValue = null;
+ return false;
+ }
+
+ internal static bool TryParse (string input, int minimalCount, out List<AuthenticationHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out AuthenticationHeaderValue parsedValue, out Token t)
+ {
+ t = lexer.Scan ();
+ if (t != Token.Type.Token) {
parsedValue = null;
return false;
}
@@ -95,8 +112,11 @@ namespace System.Net.Http.Headers
parsedValue.Scheme = lexer.GetStringValue (t);
t = lexer.Scan ();
- if (t != Token.Type.End)
+ if (t == Token.Type.Token) {
+ // TODO: Wrong with multi value parsing
parsedValue.Parameter = lexer.GetRemainingStringValue (t.StartPosition);
+ t = new Token (Token.Type.End, 0, 0);
+ }
return true;
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/CollectionParser.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/CollectionParser.cs
new file mode 100644
index 0000000000..cbaafe0f80
--- /dev/null
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/CollectionParser.cs
@@ -0,0 +1,117 @@
+//
+// CollectionParser.cs
+//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections.Generic;
+
+namespace System.Net.Http.Headers
+{
+ delegate bool ElementTryParser<T> (Lexer lexer, out T parsedValue, out Token token);
+
+ static class CollectionParser
+ {
+ public static bool TryParse<T> (string input, int minimalCount, ElementTryParser<T> parser, out List<T> result) where T : class
+ {
+ var lexer = new Lexer (input);
+ result = new List<T> ();
+
+ while (true) {
+ Token token;
+ T parsedValue;
+ if (!parser (lexer, out parsedValue, out token))
+ return false;
+
+ if (parsedValue != null)
+ result.Add (parsedValue);
+
+ if (token == Token.Type.SeparatorComma)
+ continue;
+
+ if (token == Token.Type.End) {
+ if (minimalCount > result.Count) {
+ result = null;
+ return false;
+ }
+
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ public static bool TryParse (string input, int minimalCount, out List<string> result)
+ {
+ return TryParse (input, minimalCount, TryParseStringElement, out result);
+ }
+
+ public static bool TryParseRepetition (string input, int minimalCount, out List<string> result)
+ {
+ return TryParseRepetition (input, minimalCount, TryParseStringElement, out result);
+ }
+
+ static bool TryParseStringElement (Lexer lexer, out string parsedValue, out Token t)
+ {
+ t = lexer.Scan ();
+ if (t == Token.Type.Token) {
+ parsedValue = lexer.GetStringValue (t);
+ if (parsedValue.Length == 0)
+ parsedValue = null;
+
+ t = lexer.Scan ();
+ } else {
+ parsedValue = null;
+ }
+
+ return true;
+ }
+
+ public static bool TryParseRepetition<T> (string input, int minimalCount, ElementTryParser<T> parser, out List<T> result) where T : class
+ {
+ var lexer = new Lexer (input);
+ result = new List<T> ();
+
+ while (true) {
+ Token token;
+ T parsedValue;
+ if (!parser (lexer, out parsedValue, out token))
+ return false;
+
+ if (parsedValue != null)
+ result.Add (parsedValue);
+
+ if (token == Token.Type.End) {
+ if (minimalCount > result.Count)
+ return false;
+
+ return true;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs
index a4d1ae275b..9dd41b3d33 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs
@@ -394,7 +394,7 @@ namespace System.Net.Http.Headers
switch (t.Kind) {
case Token.Type.SeparatorSemicolon:
- if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters))
+ if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters, out t) || t != Token.Type.End)
return false;
break;
case Token.Type.End:
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/EntityTagHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/EntityTagHeaderValue.cs
index 9b10983bbf..8c255cfaed 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/EntityTagHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/EntityTagHeaderValue.cs
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public class EntityTagHeaderValue : ICloneable
@@ -85,14 +87,32 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out EntityTagHeaderValue parsedValue)
{
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
parsedValue = null;
+ return false;
+ }
- var lexer = new Lexer (input);
- var t = lexer.Scan ();
+ static bool TryParseElement (Lexer lexer, out EntityTagHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ t = lexer.Scan ();
bool is_weak = false;
if (t == Token.Type.Token) {
- if (lexer.GetStringValue (t) != "W" || lexer.PeekChar () != '/')
+ var s = lexer.GetStringValue (t);
+ if (s == "*") {
+ parsedValue = any;
+
+ t = lexer.Scan ();
+ return true;
+ }
+
+ if (s != "W" || lexer.PeekChar () != '/')
return false;
is_weak = true;
@@ -103,15 +123,20 @@ namespace System.Net.Http.Headers
if (t != Token.Type.QuotedString)
return false;
- if (lexer.Scan () != Token.Type.End)
- return false;
-
parsedValue = new EntityTagHeaderValue ();
parsedValue.Tag = lexer.GetStringValue (t);
parsedValue.IsWeak = is_weak;
+
+ t = lexer.Scan ();
+
return true;
}
+ internal static bool TryParse (string input, int minimalCount, out List<EntityTagHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
public override string ToString ()
{
return IsWeak ?
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs
index 3772180e52..6337319ea1 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs
@@ -4,7 +4,7 @@
// Authors:
// Marek Safar <marek.safar@gmail.com>
//
-// Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
+// Copyright (C) 2011, 2014 Xamarin Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -32,6 +32,7 @@ using System.Collections.Generic;
namespace System.Net.Http.Headers
{
delegate bool TryParseDelegate<T> (string value, out T result);
+ delegate bool TryParseListDelegate<T> (string value, int minimalCount, out List<T> result);
abstract class HeaderInfo
{
@@ -89,6 +90,32 @@ namespace System.Net.Http.Headers
}
}
+ class CollectionHeaderTypeInfo<T, U> : HeaderTypeInfo<T, U> where U : class
+ {
+ readonly int minimalCount;
+ TryParseListDelegate<T> parser;
+
+ public CollectionHeaderTypeInfo (string name, TryParseListDelegate<T> parser, HttpHeaderKind headerKind, int minimalCount)
+ : base (name, null, headerKind)
+ {
+ this.parser = parser;
+ this.minimalCount = minimalCount;
+ AllowsMany = true;
+ }
+
+ public override bool TryParse (string value, out object result)
+ {
+ List<T> tresult;
+ if (!parser (value, minimalCount, out tresult)) {
+ result = null;
+ return false;
+ }
+
+ result = tresult;
+ return true;
+ }
+ }
+
public bool AllowsMany;
public readonly HttpHeaderKind HeaderKind;
public readonly string Name;
@@ -104,18 +131,12 @@ namespace System.Net.Http.Headers
return new HeaderTypeInfo<T, object> (name, parser, headerKind);
}
- public static HeaderInfo CreateMulti<T> (string name, TryParseDelegate<T> parser, HttpHeaderKind headerKind) where T : class
- {
- return new HeaderTypeInfo<T, T> (name, parser, headerKind) {
- AllowsMany = true,
- };
- }
-
- public static HeaderInfo CreateMultiList<T> (string name, TryParseDelegate<List<T>> parser, HttpHeaderKind headerKind) where T : class
+ //
+ // Headers with #rule for defining lists of elements or *rule for defining occurences of elements
+ //
+ public static HeaderInfo CreateMulti<T> (string name, TryParseListDelegate<T> elementParser, HttpHeaderKind headerKind, int minimalCount = 1) where T : class
{
- return new HeaderTypeInfo<List<T>, T> (name, parser, headerKind) {
- AllowsMany = true,
- };
+ return new CollectionHeaderTypeInfo<T, T> (name, elementParser, headerKind, minimalCount);
}
public object CreateCollection (HttpHeaders headers)
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs
index 1dc3affa32..ffef647b5e 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs
@@ -90,14 +90,14 @@ namespace System.Net.Http.Headers
HeaderInfo.CreateMulti<StringWithQualityHeaderValue> ("Accept-Charset", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request),
HeaderInfo.CreateMulti<StringWithQualityHeaderValue> ("Accept-Encoding", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request),
HeaderInfo.CreateMulti<StringWithQualityHeaderValue> ("Accept-Language", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request),
- HeaderInfo.CreateMulti<string> ("Accept-Ranges", Parser.Token.TryParse, HttpHeaderKind.Response),
+ HeaderInfo.CreateMulti<string> ("Accept-Ranges", CollectionParser.TryParse, HttpHeaderKind.Response),
HeaderInfo.CreateSingle<TimeSpan> ("Age", Parser.TimeSpanSeconds.TryParse, HttpHeaderKind.Response),
- HeaderInfo.CreateMulti<string> ("Allow", Parser.Token.TryParse, HttpHeaderKind.Content),
+ HeaderInfo.CreateMulti<string> ("Allow", CollectionParser.TryParse, HttpHeaderKind.Content, 0),
HeaderInfo.CreateSingle<AuthenticationHeaderValue> ("Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request),
HeaderInfo.CreateSingle<CacheControlHeaderValue> ("Cache-Control", CacheControlHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
- HeaderInfo.CreateMulti<string> ("Connection", Parser.Token.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
- HeaderInfo.CreateMulti<string> ("Content-Encoding", Parser.Token.TryParse, HttpHeaderKind.Content),
- HeaderInfo.CreateMulti<string> ("Content-Language", Parser.Token.TryParse, HttpHeaderKind.Content),
+ HeaderInfo.CreateMulti<string> ("Connection", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
+ HeaderInfo.CreateMulti<string> ("Content-Encoding", CollectionParser.TryParse, HttpHeaderKind.Content),
+ HeaderInfo.CreateMulti<string> ("Content-Language", CollectionParser.TryParse, HttpHeaderKind.Content),
HeaderInfo.CreateSingle<long> ("Content-Length", Parser.Long.TryParse, HttpHeaderKind.Content),
HeaderInfo.CreateSingle<Uri> ("Content-Location", Parser.Uri.TryParse, HttpHeaderKind.Content),
HeaderInfo.CreateSingle<byte[]> ("Content-MD5", Parser.MD5.TryParse, HttpHeaderKind.Content),
@@ -117,19 +117,19 @@ namespace System.Net.Http.Headers
HeaderInfo.CreateSingle<DateTimeOffset> ("Last-Modified", Parser.DateTime.TryParse, HttpHeaderKind.Content),
HeaderInfo.CreateSingle<Uri> ("Location", Parser.Uri.TryParse, HttpHeaderKind.Response),
HeaderInfo.CreateSingle<int> ("Max-Forwards", Parser.Int.TryParse, HttpHeaderKind.Request),
- HeaderInfo.CreateMultiList<NameValueHeaderValue> ("Pragma", NameValueHeaderValue.TryParsePragma, HttpHeaderKind.Request | HttpHeaderKind.Response),
+ HeaderInfo.CreateMulti<NameValueHeaderValue> ("Pragma", NameValueHeaderValue.TryParsePragma, HttpHeaderKind.Request | HttpHeaderKind.Response),
HeaderInfo.CreateMulti<AuthenticationHeaderValue> ("Proxy-Authenticate", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Response),
HeaderInfo.CreateSingle<AuthenticationHeaderValue> ("Proxy-Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request),
HeaderInfo.CreateSingle<RangeHeaderValue> ("Range", RangeHeaderValue.TryParse, HttpHeaderKind.Request),
HeaderInfo.CreateSingle<Uri> ("Referer", Parser.Uri.TryParse, HttpHeaderKind.Request),
HeaderInfo.CreateSingle<RetryConditionHeaderValue> ("Retry-After", RetryConditionHeaderValue.TryParse, HttpHeaderKind.Response),
HeaderInfo.CreateMulti<ProductInfoHeaderValue> ("Server", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Response),
- HeaderInfo.CreateMulti<TransferCodingWithQualityHeaderValue> ("TE", TransferCodingWithQualityHeaderValue.TryParse, HttpHeaderKind.Request),
- HeaderInfo.CreateMulti<string> ("Trailer", Parser.Token.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
+ HeaderInfo.CreateMulti<TransferCodingWithQualityHeaderValue> ("TE", TransferCodingWithQualityHeaderValue.TryParse, HttpHeaderKind.Request, 0),
+ HeaderInfo.CreateMulti<string> ("Trailer", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
HeaderInfo.CreateMulti<TransferCodingHeaderValue> ("Transfer-Encoding", TransferCodingHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
HeaderInfo.CreateMulti<ProductHeaderValue> ("Upgrade", ProductHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
- HeaderInfo.CreateMultiList<ProductInfoHeaderValue> ("User-Agent", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Request),
- HeaderInfo.CreateMulti<string> ("Vary", Parser.Token.TryParse, HttpHeaderKind.Response),
+ HeaderInfo.CreateMulti<ProductInfoHeaderValue> ("User-Agent", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Request),
+ HeaderInfo.CreateMulti<string> ("Vary", CollectionParser.TryParse, HttpHeaderKind.Response),
HeaderInfo.CreateMulti<ViaHeaderValue> ("Via", ViaHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
HeaderInfo.CreateMulti<WarningHeaderValue> ("Warning", WarningHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
HeaderInfo.CreateMulti<AuthenticationHeaderValue> ("WWW-Authenticate", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Response)
@@ -231,16 +231,9 @@ namespace System.Net.Http.Headers
if (values == null)
throw new ArgumentNullException ("values");
- if (string.IsNullOrEmpty (name))
- return false;
-
- Parser.Token.Check (name);
-
HeaderInfo headerInfo;
- if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) {
- if (HeaderKind != HttpHeaderKind.None && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0)
- return false;
- }
+ if (!TryCheckName (name, out headerInfo))
+ return false;
AddInternal (name, values, null, true);
return true;
@@ -264,6 +257,21 @@ namespace System.Net.Http.Headers
return headerInfo;
}
+ bool TryCheckName (string name, out HeaderInfo headerInfo)
+ {
+ if (!Parser.Token.TryCheck (name)) {
+ headerInfo = null;
+ return false;
+ }
+
+ if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) {
+ if (HeaderKind != HttpHeaderKind.None && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0)
+ return false;
+ }
+
+ return true;
+ }
+
public void Clear ()
{
connectionclose = null;
@@ -301,6 +309,8 @@ namespace System.Net.Http.Headers
public IEnumerable<string> GetValues (string name)
{
+ CheckName (name);
+
IEnumerable<string> values;
if (!TryGetValues (name, out values))
throw new InvalidOperationException ();
@@ -316,7 +326,11 @@ namespace System.Net.Http.Headers
public bool TryGetValues (string name, out IEnumerable<string> values)
{
- var header_info = CheckName (name);
+ HeaderInfo headerInfo;
+ if (!TryCheckName (name, out headerInfo)) {
+ values = null;
+ return false;
+ }
HeaderBucket bucket;
if (!headers.TryGetValue (name, out bucket)) {
@@ -324,7 +338,7 @@ namespace System.Net.Http.Headers
return false;
}
- values = GetAllHeaderValues (bucket, header_info);
+ values = GetAllHeaderValues (bucket, headerInfo);
return true;
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs
index 0f98be658d..f87d4f741b 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs
@@ -46,6 +46,8 @@ namespace System.Net.Http.Headers
OpenParens,
}
+ public static readonly Token Empty = new Token (Type.Token, 0, 0);
+
readonly Type type;
public Token (Type type, int startPosition, int endPosition)
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeHeaderValue.cs
index 5379a6099f..296010aa2a 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeHeaderValue.cs
@@ -33,7 +33,7 @@ namespace System.Net.Http.Headers
public class MediaTypeHeaderValue : ICloneable
{
internal List<NameValueHeaderValue> parameters;
- string media_type;
+ internal string media_type;
public MediaTypeHeaderValue (string mediaType)
{
@@ -150,7 +150,8 @@ namespace System.Net.Http.Headers
switch (token.Value.Kind) {
case Token.Type.SeparatorSemicolon:
- if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters))
+ Token t;
+ if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters, out t) || t != Token.Type.End)
return false;
break;
case Token.Type.End:
@@ -167,37 +168,7 @@ namespace System.Net.Http.Headers
return true;
}
- internal static bool TryParse<T> (string input, out T parsedValue, Func<T> factory) where T : MediaTypeHeaderValue
- {
- parsedValue = null;
-
- var lexer = new Lexer (input);
-
- string media;
- List<NameValueHeaderValue> parameters = null;
- var token = TryParseMediaType (lexer, out media);
- if (token == null)
- return false;
-
- switch (token.Value.Kind) {
- case Token.Type.SeparatorSemicolon:
- if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters))
- return false;
- break;
- case Token.Type.End:
- break;
- default:
- return false;
- }
-
- parsedValue = factory ();
- parsedValue.media_type = media;
- parsedValue.parameters = parameters;
-
- return true;
- }
-
- static Token? TryParseMediaType (Lexer lexer, out string media)
+ internal static Token? TryParseMediaType (Lexer lexer, out string media)
{
media = null;
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs
index a3415fc1e1..1cf406dbfd 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public sealed class MediaTypeWithQualityHeaderValue : MediaTypeHeaderValue
@@ -65,7 +67,40 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out MediaTypeWithQualityHeaderValue parsedValue)
{
- return TryParse (input, out parsedValue, () => new MediaTypeWithQualityHeaderValue ());
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
+ parsedValue = null;
+ return false;
+ }
+
+ static bool TryParseElement (Lexer lexer, out MediaTypeWithQualityHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ string media;
+ List<NameValueHeaderValue> parameters = null;
+ var token = TryParseMediaType (lexer, out media);
+ if (token == null) {
+ t = Token.Empty;
+ return false;
+ }
+
+ t = token.Value;
+ if (t == Token.Type.SeparatorSemicolon && (!NameValueHeaderValue.TryParseParameters (lexer, out parameters, out t) || t != Token.Type.End))
+ return false;
+
+ parsedValue = new MediaTypeWithQualityHeaderValue ();
+ parsedValue.media_type = media;
+ parsedValue.parameters = parameters;
+ return true;
+ }
+
+ internal static bool TryParse (string input, int minimalCount, out List<MediaTypeWithQualityHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
}
}
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueHeaderValue.cs
index 906ab3aa65..e3766a4eb1 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueHeaderValue.cs
@@ -32,7 +32,7 @@ namespace System.Net.Http.Headers
{
public class NameValueHeaderValue : ICloneable
{
- string value;
+ internal string value;
public NameValueHeaderValue (string name)
: this (name, null)
@@ -53,11 +53,11 @@ namespace System.Net.Http.Headers
this.value = source.value;
}
- private NameValueHeaderValue ()
+ internal NameValueHeaderValue ()
{
}
- public string Name { get; private set; }
+ public string Name { get; internal set; }
public string Value {
get {
@@ -121,27 +121,22 @@ namespace System.Net.Http.Headers
throw new FormatException (input);
}
- internal static bool TryParseParameters (Lexer lexer, out List<NameValueHeaderValue> result)
+ internal static bool TryParsePragma (string input, int minimalCount, out List<NameValueHeaderValue> result)
{
- return TryParseCollection (lexer, out result, Token.Type.SeparatorSemicolon);
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
}
- internal static bool TryParsePragma (string input, out List<NameValueHeaderValue> result)
- {
- return TryParseCollection (new Lexer (input), out result, Token.Type.SeparatorComma);
- }
-
- static bool TryParseCollection (Lexer lexer, out List<NameValueHeaderValue> result, Token.Type separator)
+ internal static bool TryParseParameters (Lexer lexer, out List<NameValueHeaderValue> result, out Token t)
{
var list = new List<NameValueHeaderValue> ();
result = null;
- Token t;
-
- do {
+ while (true) {
var attr = lexer.Scan ();
- if (attr != Token.Type.Token)
+ if (attr != Token.Type.Token) {
+ t = Token.Empty;
return false;
+ }
string value = null;
@@ -156,19 +151,17 @@ namespace System.Net.Http.Headers
t = lexer.Scan ();
}
- if (t == separator|| t == Token.Type.End) {
- list.Add (new NameValueHeaderValue () {
- Name = lexer.GetStringValue (attr),
- value = value
- });
- } else {
- return false;
- }
+ list.Add (new NameValueHeaderValue () {
+ Name = lexer.GetStringValue (attr),
+ value = value
+ });
- } while (t == separator);
+ if (t == Token.Type.SeparatorSemicolon)
+ continue;
- result = list;
- return true;
+ result = list;
+ return true;
+ }
}
public override string ToString ()
@@ -181,35 +174,39 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out NameValueHeaderValue parsedValue)
{
- parsedValue = null;
-
var lexer = new Lexer (input);
- var t = lexer.Scan ();
- if (t != Token.Type.Token && t != Token.Type.QuotedString)
- return false;
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
- string v = null;
- var token2 = lexer.Scan ();
- if (token2 != Token.Type.End) {
- if (token2 != Token.Type.SeparatorEqual)
- return false;
-
- token2 = lexer.Scan ();
+ parsedValue = null;
+ return false;
+ }
- if (token2 == Token.Type.Token || token2 == Token.Type.QuotedString) {
- v = lexer.GetStringValue (token2);
- token2 = lexer.Scan ();
- }
+ static bool TryParseElement (Lexer lexer, out NameValueHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
- if (token2 != Token.Type.End)
- return false;
- }
+ t = lexer.Scan ();
+ if (t != Token.Type.Token)
+ return false;
parsedValue = new NameValueHeaderValue () {
Name = lexer.GetStringValue (t),
- value = v
};
+ t = lexer.Scan ();
+ if (t == Token.Type.SeparatorEqual) {
+ t = lexer.Scan ();
+
+ if (t == Token.Type.Token || t == Token.Type.QuotedString) {
+ parsedValue.value = lexer.GetStringValue (t);
+ t = lexer.Scan ();
+ } else {
+ return false;
+ }
+ }
+
return true;
}
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs
index 81d7bb089c..3d32834184 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs
@@ -53,8 +53,8 @@ namespace System.Net.Http.Headers
}
}
- private NameValueWithParametersHeaderValue (NameValueHeaderValue source)
- : base (source)
+ private NameValueWithParametersHeaderValue ()
+ : base ()
{
}
@@ -102,15 +102,52 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out NameValueWithParametersHeaderValue parsedValue)
{
- List<NameValueHeaderValue> values;
- if (!TryParseParameters (new Lexer (input), out values)) {
- parsedValue = null;
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
+ parsedValue = null;
+ return false;
+ }
+
+ internal static bool TryParse (string input, int minimalCount, out List<NameValueWithParametersHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out NameValueWithParametersHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ t = lexer.Scan ();
+ if (t != Token.Type.Token)
return false;
+
+ parsedValue = new NameValueWithParametersHeaderValue () {
+ Name = lexer.GetStringValue (t),
+ };
+
+ t = lexer.Scan ();
+ if (t == Token.Type.SeparatorEqual) {
+ t = lexer.Scan ();
+
+ if (t == Token.Type.Token || t == Token.Type.QuotedString) {
+ parsedValue.value = lexer.GetStringValue (t);
+ t = lexer.Scan ();
+ } else {
+ return false;
+ }
+ }
+
+ if (t == Token.Type.SeparatorSemicolon) {
+ List<NameValueHeaderValue> result;
+ if (!TryParseParameters (lexer, out result, out t))
+ return false;
+
+ parsedValue.parameters = result;
}
- parsedValue = new NameValueWithParametersHeaderValue (values[0]);
- values.RemoveAt (0);
- parsedValue.parameters = values;
return true;
}
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/Parser.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/Parser.cs
index cdf73d3a78..79a3ca380c 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/Parser.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/Parser.cs
@@ -28,6 +28,7 @@
using System.Net.Mail;
using System.Globalization;
+using System.Collections.Generic;
namespace System.Net.Http.Headers
{
@@ -64,14 +65,7 @@ namespace System.Net.Http.Headers
if (s == null)
return false;
- if (!Lexer.IsValidToken (s)) {
- if (s.Length == 0)
- return false;
-
- return false;
- }
-
- return true;
+ return Lexer.IsValidToken (s);
}
public static void CheckQuotedString (string s)
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductHeaderValue.cs
index 306c9f228c..9614df1293 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductHeaderValue.cs
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public class ProductHeaderValue : ICloneable
@@ -87,15 +89,30 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out ProductHeaderValue parsedValue)
{
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
parsedValue = null;
+ return false;
+ }
- var lexer = new Lexer (input);
- var t = lexer.Scan ();
+ internal static bool TryParse (string input, int minimalCount, out List<ProductHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out ProductHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ t = lexer.Scan ();
if (t != Token.Type.Token)
return false;
- var value = new ProductHeaderValue ();
- value.Name = lexer.GetStringValue (t);
+ parsedValue = new ProductHeaderValue ();
+ parsedValue.Name = lexer.GetStringValue (t);
t = lexer.Scan ();
if (t == Token.Type.SeparatorSlash) {
@@ -103,14 +120,10 @@ namespace System.Net.Http.Headers
if (t != Token.Type.Token)
return false;
- value.Version = lexer.GetStringValue (t);
+ parsedValue.Version = lexer.GetStringValue (t);
t = lexer.Scan ();
}
- if (t != Token.Type.End)
- return false;
-
- parsedValue = value;
return true;
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductInfoHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductInfoHeaderValue.cs
index daf47ac31e..baace53ed8 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductInfoHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ProductInfoHeaderValue.cs
@@ -106,7 +106,7 @@ namespace System.Net.Http.Headers
return true;
}
- internal static bool TryParse (string input, out List<ProductInfoHeaderValue> result)
+ internal static bool TryParse (string input, int minimalCount, out List<ProductInfoHeaderValue> result)
{
var list = new List<ProductInfoHeaderValue> ();
var lexer = new Lexer (input);
@@ -118,8 +118,12 @@ namespace System.Net.Http.Headers
return false;
if (element == null) {
- result = list;
- return true;
+ if (list != null && minimalCount <= list.Count) {
+ result = list;
+ return true;
+ }
+
+ return false;
}
list.Add (element);
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/StringWithQualityHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/StringWithQualityHeaderValue.cs
index 635ed00223..648d4222e3 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/StringWithQualityHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/StringWithQualityHeaderValue.cs
@@ -27,6 +27,8 @@
//
using System.Globalization;
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public class StringWithQualityHeaderValue : ICloneable
@@ -82,10 +84,24 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out StringWithQualityHeaderValue parsedValue)
{
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
parsedValue = null;
+ return false;
+ }
- var lexer = new Lexer (input);
- var t = lexer.Scan ();
+ internal static bool TryParse (string input, int minimalCount, out List<StringWithQualityHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out StringWithQualityHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+ t = lexer.Scan ();
if (t != Token.Type.Token)
return false;
@@ -120,9 +136,6 @@ namespace System.Net.Http.Headers
t = lexer.Scan ();
}
- if (t != Token.Type.End)
- return false;
-
parsedValue = value;
return true;
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingHeaderValue.cs
index 8f0db59283..6e9825ea4c 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingHeaderValue.cs
@@ -32,7 +32,7 @@ namespace System.Net.Http.Headers
{
public class TransferCodingHeaderValue : ICloneable
{
- string value;
+ internal string value;
internal List<NameValueHeaderValue> parameters;
public TransferCodingHeaderValue (string value)
@@ -106,30 +106,36 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out TransferCodingHeaderValue parsedValue)
{
- return TryParse (input, out parsedValue, () => new TransferCodingHeaderValue ());
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
+ parsedValue = null;
+ return false;
}
- internal static bool TryParse<T> (string input, out T parsedValue, Func<T> factory) where T : TransferCodingHeaderValue
+ internal static bool TryParse (string input, int minimalCount, out List<TransferCodingHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out TransferCodingHeaderValue parsedValue, out Token t)
{
parsedValue = null;
- var lexer = new Lexer (input);
- var t = lexer.Scan ();
+ t = lexer.Scan ();
if (t != Token.Type.Token)
return false;
- var result = factory ();
+ var result = new TransferCodingHeaderValue ();
result.value = lexer.GetStringValue (t);
t = lexer.Scan ();
// Parameters parsing
- if (t == Token.Type.SeparatorSemicolon) {
- if (!NameValueHeaderValue.TryParseParameters (lexer, out result.parameters))
- return false;
- } else if (t != Token.Type.End) {
+ if (t == Token.Type.SeparatorSemicolon && (!NameValueHeaderValue.TryParseParameters (lexer, out result.parameters, out t) || t != Token.Type.End))
return false;
- }
parsedValue = result;
return true;
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs
index 0a6e08373c..845b95ef5c 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public sealed class TransferCodingWithQualityHeaderValue : TransferCodingHeaderValue
@@ -65,7 +67,39 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out TransferCodingWithQualityHeaderValue parsedValue)
{
- return TryParse (input, out parsedValue, () => new TransferCodingWithQualityHeaderValue ());
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
+ parsedValue = null;
+ return false;
+ }
+
+ internal static bool TryParse (string input, int minimalCount, out List<TransferCodingWithQualityHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out TransferCodingWithQualityHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ t = lexer.Scan ();
+ if (t != Token.Type.Token)
+ return false;
+
+ var result = new TransferCodingWithQualityHeaderValue ();
+ result.value = lexer.GetStringValue (t);
+
+ t = lexer.Scan ();
+
+ // Parameters parsing
+ if (t == Token.Type.SeparatorSemicolon && (!NameValueHeaderValue.TryParseParameters (lexer, out result.parameters, out t) || t != Token.Type.End))
+ return false;
+
+ parsedValue = result;
+ return true;
}
}
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ViaHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ViaHeaderValue.cs
index 4da14004e1..9381977ee1 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ViaHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ViaHeaderValue.cs
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
+
namespace System.Net.Http.Headers
{
public class ViaHeaderValue : ICloneable
@@ -110,11 +112,25 @@ namespace System.Net.Http.Headers
public static bool TryParse (string input, out ViaHeaderValue parsedValue)
{
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
parsedValue = null;
+ return false;
+ }
- var lexer = new Lexer (input);
+ internal static bool TryParse (string input, int minimalCount, out List<ViaHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
- var t = lexer.Scan ();
+ static bool TryParseElement (Lexer lexer, out ViaHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ t = lexer.Scan ();
if (t != Token.Type.Token)
return false;
@@ -150,8 +166,9 @@ namespace System.Net.Http.Headers
value.ReceivedBy = lexer.GetStringValue (next, t);
string comment;
- if (!lexer.ScanCommentOptional (out comment))
- return false;
+ if (lexer.ScanCommentOptional (out comment, out t)) {
+ t = lexer.Scan ();
+ }
value.Comment = comment;
parsedValue = value;
diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/WarningHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/WarningHeaderValue.cs
index fc58299cf0..5c65339ef7 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.Headers/WarningHeaderValue.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/WarningHeaderValue.cs
@@ -27,6 +27,7 @@
//
using System.Globalization;
+using System.Collections.Generic;
namespace System.Net.Http.Headers
{
@@ -100,13 +101,28 @@ namespace System.Net.Http.Headers
throw new FormatException (input);
}
-
+
public static bool TryParse (string input, out WarningHeaderValue parsedValue)
{
+ var lexer = new Lexer (input);
+ Token token;
+ if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
+ return true;
+
parsedValue = null;
+ return false;
+ }
- var lexer = new Lexer (input);
- var t = lexer.Scan ();
+ internal static bool TryParse (string input, int minimalCount, out List<WarningHeaderValue> result)
+ {
+ return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
+ }
+
+ static bool TryParseElement (Lexer lexer, out WarningHeaderValue parsedValue, out Token t)
+ {
+ parsedValue = null;
+
+ t = lexer.Scan ();
if (t != Token.Type.Token)
return false;
@@ -148,9 +164,6 @@ namespace System.Net.Http.Headers
t = lexer.Scan ();
}
- if (t != Token.Type.End)
- return false;
-
parsedValue = value;
return true;
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http.dll.sources b/mcs/class/System.Net.Http/System.Net.Http.dll.sources
index ccca104fd9..b40b2a170c 100644
--- a/mcs/class/System.Net.Http/System.Net.Http.dll.sources
+++ b/mcs/class/System.Net.Http/System.Net.Http.dll.sources
@@ -22,6 +22,7 @@ System.Net.Http/StringContent.cs
System.Net.Http.Headers/AuthenticationHeaderValue.cs
System.Net.Http.Headers/CacheControlHeaderValue.cs
System.Net.Http.Headers/CollectionExtensions.cs
+System.Net.Http.Headers/CollectionParser.cs
System.Net.Http.Headers/ContentDispositionHeaderValue.cs
System.Net.Http.Headers/ContentRangeHeaderValue.cs
System.Net.Http.Headers/EntityTagHeaderValue.cs
diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
index 656911ee0e..354dba96bf 100644
--- a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
@@ -247,7 +247,8 @@ namespace System.Net.Http
wr.PreAuthenticate = preAuthenticate;
if (useCookies) {
- wr.CookieContainer = cookieContainer;
+ // It cannot be null or allowAutoRedirect won't work
+ wr.CookieContainer = CookieContainer;
}
if (useDefaultCredentials) {
@@ -271,12 +272,12 @@ namespace System.Net.Http
return wr;
}
- HttpResponseMessage CreateResponseMessage (HttpWebResponse wr, HttpRequestMessage requestMessage)
+ HttpResponseMessage CreateResponseMessage (HttpWebResponse wr, HttpRequestMessage requestMessage, CancellationToken cancellationToken)
{
var response = new HttpResponseMessage (wr.StatusCode);
response.RequestMessage = requestMessage;
response.ReasonPhrase = wr.StatusDescription;
- response.Content = new StreamContent (wr.GetResponseStream ());
+ response.Content = new StreamContent (wr.GetResponseStream (), cancellationToken);
var headers = wr.Headers;
for (int i = 0; i < headers.Count; ++i) {
@@ -328,7 +329,7 @@ namespace System.Net.Http
}
}
- return CreateResponseMessage (wresponse, request);
+ return CreateResponseMessage (wresponse, request, cancellationToken);
}
}
}
diff --git a/mcs/class/System.Net.Http/System.Net.Http/StreamContent.cs b/mcs/class/System.Net.Http/System.Net.Http/StreamContent.cs
index 9dabf983b6..a249aad6f5 100644
--- a/mcs/class/System.Net.Http/System.Net.Http/StreamContent.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http/StreamContent.cs
@@ -27,6 +27,7 @@
//
using System.IO;
+using System.Threading;
using System.Threading.Tasks;
namespace System.Net.Http
@@ -35,6 +36,7 @@ namespace System.Net.Http
{
readonly Stream content;
readonly int bufferSize;
+ readonly CancellationToken cancellationToken;
public StreamContent (Stream content)
: this (content, 16 * 1024)
@@ -53,6 +55,18 @@ namespace System.Net.Http
this.bufferSize = bufferSize;
}
+ //
+ // Workarounds for poor .NET API
+ // Instead of having SerializeToStreamAsync with CancellationToken as public API. Only LoadIntoBufferAsync
+ // called internally from the send worker can be cancelled and user cannot see/do it
+ //
+ internal StreamContent (Stream content, CancellationToken cancellationToken)
+ : this (content)
+ {
+ // We don't own the token so don't worry about disposing it
+ this.cancellationToken = cancellationToken;
+ }
+
protected override Task<Stream> CreateContentReadStreamAsync ()
{
return Task.FromResult (content);
@@ -69,7 +83,7 @@ namespace System.Net.Http
protected internal override Task SerializeToStreamAsync (Stream stream, TransportContext context)
{
- return content.CopyToAsync (stream, bufferSize);
+ return content.CopyToAsync (stream, bufferSize, cancellationToken);
}
protected internal override bool TryComputeLength (out long length)
diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeadersTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeadersTest.cs
index a4b2555160..cae4a65c82 100644
--- a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeadersTest.cs
+++ b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeadersTest.cs
@@ -131,6 +131,14 @@ namespace MonoTests.System.Net.Http.Headers
}
[Test]
+ public void TryGetValuesTest ()
+ {
+ IEnumerable<string> headerValues;
+ Assert.IsFalse (headers.TryGetValues (null, out headerValues), "#1");
+ Assert.IsFalse (headers.TryGetValues ("some-name", out headerValues), "#2");
+ }
+
+ [Test]
public void ToStringTest ()
{
headers.Add ("aa", "v");
diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/NameValueHeaderValueTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/NameValueHeaderValueTest.cs
index 7d08832868..32cf785a0e 100644
--- a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/NameValueHeaderValueTest.cs
+++ b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/NameValueHeaderValueTest.cs
@@ -157,6 +157,9 @@ namespace MonoTests.System.Net.Http.Headers
NameValueHeaderValue res;
Assert.IsFalse (NameValueHeaderValue.TryParse ("", out res), "#1");
Assert.IsNull (res, "#2");
+
+ Assert.IsFalse (NameValueHeaderValue.TryParse ("\"a\"=b", out res), "#3");
+ Assert.IsNull (res, "#4");
}
}
}
diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpRequestMessageTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpRequestMessageTest.cs
index b852fdc05f..79ae114f65 100644
--- a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpRequestMessageTest.cs
+++ b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpRequestMessageTest.cs
@@ -35,6 +35,7 @@ using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;
using System.Linq;
+using System.IO;
namespace MonoTests.System.Net.Http
{
@@ -361,15 +362,55 @@ namespace MonoTests.System.Net.Http
}
[Test]
- public void Headers_Complex ()
+ public void Headers_MultiValues ()
{
HttpRequestMessage message = new HttpRequestMessage ();
HttpRequestHeaders headers = message.Headers;
+ headers.Add ("Accept", "application/vnd.citrix.requesttokenresponse+xml, application/vnd.citrix.requesttokenchoices+xml");
+ headers.Add ("Accept-Charset", "aa ;Q=0,bb;Q=1");
+ headers.Add ("Expect", "x=1; v, y=5");
+ headers.Add ("If-Match", "\"a\",*, \"b\",*");
headers.Add ("user-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36");
+ Assert.AreEqual (2, headers.Accept.Count, "#1a");
+ Assert.IsTrue (headers.Accept.SequenceEqual (
+ new[] {
+ new MediaTypeWithQualityHeaderValue ("application/vnd.citrix.requesttokenresponse+xml"),
+ new MediaTypeWithQualityHeaderValue ("application/vnd.citrix.requesttokenchoices+xml"),
+ }
+ ), "#1b");
- Assert.AreEqual (6, headers.UserAgent.Count);
+ Assert.AreEqual (2, headers.AcceptCharset.Count, "#2a");
+ Assert.IsTrue (headers.AcceptCharset.SequenceEqual (
+ new[] {
+ new StringWithQualityHeaderValue ("aa", 0),
+ new StringWithQualityHeaderValue ("bb", 1),
+ }
+ ), "#2b");
+
+ Assert.AreEqual (2, headers.Expect.Count, "#3a");
+ var expect_expected = new[] {
+ new NameValueWithParametersHeaderValue ("x", "1") {
+ },
+ new NameValueWithParametersHeaderValue ("y", "5"),
+ };
+ expect_expected [0].Parameters.Add (new NameValueHeaderValue ("v"));
+ Assert.IsTrue (headers.Expect.SequenceEqual (
+ expect_expected
+ ), "#3b");
+
+ Assert.AreEqual (4, headers.IfMatch.Count, "#4a");
+ Assert.IsTrue (headers.IfMatch.SequenceEqual (
+ new[] {
+ new EntityTagHeaderValue ("\"a\""),
+ EntityTagHeaderValue.Any,
+ new EntityTagHeaderValue ("\"b\""),
+ EntityTagHeaderValue.Any
+ }
+ ), "#4b");
+
+ Assert.AreEqual (6, headers.UserAgent.Count, "#10a");
Assert.IsTrue (headers.UserAgent.SequenceEqual (
new[] {
@@ -380,7 +421,7 @@ namespace MonoTests.System.Net.Http
new ProductInfoHeaderValue ("Chrome", "29.0.1547.62"),
new ProductInfoHeaderValue ("Safari", "537.36")
}
- ));
+ ), "#10b");
}
[Test]
diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpResponseMessageTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpResponseMessageTest.cs
index b92b3e644d..b13e8cae41 100644
--- a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpResponseMessageTest.cs
+++ b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpResponseMessageTest.cs
@@ -295,6 +295,56 @@ namespace MonoTests.System.Net.Http
}
[Test]
+ public void Headers_MultiValues ()
+ {
+ var message = new HttpResponseMessage ();
+ var headers = message.Headers;
+
+ headers.Add ("Proxy-Authenticate", "x, y, z,i");
+ headers.Add ("Upgrade", "HTTP/2.0, SHTTP/1.3, IRC, RTA/x11");
+ headers.Add ("Via", "1.0 fred, 1.1 nowhere.com (Apache/1.1)");
+ headers.Add ("Warning", "199 Miscellaneous \"w\", 200 a \"b\"");
+
+ Assert.AreEqual (4, headers.ProxyAuthenticate.Count, "#1a");
+ Assert.IsTrue (headers.ProxyAuthenticate.SequenceEqual (
+ new[] {
+ new AuthenticationHeaderValue ("x"),
+
+ new AuthenticationHeaderValue ("y"),
+ new AuthenticationHeaderValue ("z"),
+ new AuthenticationHeaderValue ("i")
+ }
+ ), "#1b");
+
+
+ Assert.AreEqual (4, headers.Upgrade.Count, "#2a");
+ Assert.IsTrue (headers.Upgrade.SequenceEqual (
+ new[] {
+ new ProductHeaderValue ("HTTP", "2.0"),
+ new ProductHeaderValue ("SHTTP", "1.3"),
+ new ProductHeaderValue ("IRC"),
+ new ProductHeaderValue ("RTA", "x11")
+ }
+ ), "#2b");
+
+ Assert.AreEqual (2, headers.Via.Count, "#3a");
+ Assert.IsTrue (headers.Via.SequenceEqual (
+ new[] {
+ new ViaHeaderValue ("1.0", "fred"),
+ new ViaHeaderValue ("1.1", "nowhere.com", null, "(Apache/1.1)")
+ }
+ ), "#2b");
+
+ Assert.AreEqual (2, headers.Warning.Count, "#4a");
+ Assert.IsTrue (headers.Warning.SequenceEqual (
+ new[] {
+ new WarningHeaderValue (199, "Miscellaneous", "\"w\""),
+ new WarningHeaderValue (200, "a", "\"b\"")
+ }
+ ), "#4b");
+ }
+
+ [Test]
public void Header_BaseImplementation ()
{
HttpResponseMessage message = new HttpResponseMessage ();
diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs
index edd4b839c1..413e459526 100644
--- a/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs
+++ b/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs
@@ -309,6 +309,21 @@ namespace MonoTests.System.Net.Http
}
[Test]
+ public void Headers_Multi ()
+ {
+ var sc = new StreamContent (MemoryStream.Null);
+ var headers = sc.Headers;
+
+ headers.Add ("Allow", "");
+ headers.Add ("Allow", "a , b, c");
+
+ Assert.AreEqual (3, headers.Allow.Count, "#1a");
+ Assert.IsTrue (headers.Allow.SequenceEqual (
+ new[] { "a", "b", "c" }
+ ), "#1b");
+ }
+
+ [Test]
public void LoadIntoBuffer ()
{
var ms = new MemoryStream ();
diff --git a/mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources b/mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources
new file mode 100644
index 0000000000..ccca104fd9
--- /dev/null
+++ b/mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources
@@ -0,0 +1,53 @@
+../../build/common/Consts.cs
+Assembly/AssemblyInfo.cs
+System.Net.Http/ByteArrayContent.cs
+System.Net.Http/ClientCertificateOption.cs
+System.Net.Http/DelegatingHandler.cs
+System.Net.Http/FormUrlEncodedContent.cs
+System.Net.Http/HttpClient.cs
+System.Net.Http/HttpClientHandler.cs
+System.Net.Http/HttpCompletionOption.cs
+System.Net.Http/HttpContent.cs
+System.Net.Http/HttpMessageHandler.cs
+System.Net.Http/HttpMessageInvoker.cs
+System.Net.Http/HttpMethod.cs
+System.Net.Http/HttpRequestException.cs
+System.Net.Http/HttpRequestMessage.cs
+System.Net.Http/HttpResponseMessage.cs
+System.Net.Http/MessageProcessingHandler.cs
+System.Net.Http/MultipartContent.cs
+System.Net.Http/MultipartFormDataContent.cs
+System.Net.Http/StreamContent.cs
+System.Net.Http/StringContent.cs
+System.Net.Http.Headers/AuthenticationHeaderValue.cs
+System.Net.Http.Headers/CacheControlHeaderValue.cs
+System.Net.Http.Headers/CollectionExtensions.cs
+System.Net.Http.Headers/ContentDispositionHeaderValue.cs
+System.Net.Http.Headers/ContentRangeHeaderValue.cs
+System.Net.Http.Headers/EntityTagHeaderValue.cs
+System.Net.Http.Headers/HashCodeCalculator.cs
+System.Net.Http.Headers/HeaderInfo.cs
+System.Net.Http.Headers/HttpContentHeaders.cs
+System.Net.Http.Headers/HttpHeaderKind.cs
+System.Net.Http.Headers/HttpHeaders.cs
+System.Net.Http.Headers/HttpHeaderValueCollection.cs
+System.Net.Http.Headers/HttpRequestHeaders.cs
+System.Net.Http.Headers/HttpResponseHeaders.cs
+System.Net.Http.Headers/Lexer.cs
+System.Net.Http.Headers/MediaTypeHeaderValue.cs
+System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs
+System.Net.Http.Headers/NameValueHeaderValue.cs
+System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs
+System.Net.Http.Headers/Parser.cs
+System.Net.Http.Headers/ProductHeaderValue.cs
+System.Net.Http.Headers/ProductInfoHeaderValue.cs
+System.Net.Http.Headers/QualityValue.cs
+System.Net.Http.Headers/RangeConditionHeaderValue.cs
+System.Net.Http.Headers/RangeHeaderValue.cs
+System.Net.Http.Headers/RangeItemHeaderValue.cs
+System.Net.Http.Headers/RetryConditionHeaderValue.cs
+System.Net.Http.Headers/StringWithQualityHeaderValue.cs
+System.Net.Http.Headers/TransferCodingHeaderValue.cs
+System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs
+System.Net.Http.Headers/ViaHeaderValue.cs
+System.Net.Http.Headers/WarningHeaderValue.cs \ No newline at end of file