소스 검색

Correctly parse pragma headers. Fixes #13501

Marek Safar 12 년 전
부모
커밋
12aa2ee3ca

+ 1 - 1
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.ParseParameters (lexer, out parameters))
+				if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters))
 					return false;
 				break;
 			case Token.Type.End:

+ 13 - 1
mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs

@@ -50,7 +50,12 @@ namespace System.Net.Http.Headers
 				Debug.Assert (AllowsMany);
 
 				var c = (HttpHeaderValueCollection<U>) collection;
-				c.Add ((U) value);
+
+				var list = value as List<U>;
+				if (list != null)
+					c.AddRange (list);
+				else
+					c.Add ((U) value);
 			}
 
 			protected override object CreateCollection (HttpHeaders headers, HeaderInfo headerInfo)
@@ -106,6 +111,13 @@ namespace System.Net.Http.Headers
 			};
 		}
 
+		public static HeaderInfo CreateMultiList<T> (string name, TryParseDelegate<List<T>> parser, HttpHeaderKind headerKind) where T : class
+		{
+			return new HeaderTypeInfo<List<T>, T> (name, parser, headerKind) {
+				AllowsMany = true,
+			};
+		}
+
 		public object CreateCollection (HttpHeaders headers)
 		{
 			return CreateCollection (headers, this);

+ 5 - 0
mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaderValueCollection.cs

@@ -61,6 +61,11 @@ namespace System.Net.Http.Headers
 			list.Add (item);
 		}
 
+		internal void AddRange (List<T> values)
+		{
+			list.AddRange (values);
+		}
+
 		public void Clear ()
 		{
 			list.Clear ();

+ 1 - 1
mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs

@@ -117,7 +117,7 @@ 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.CreateMulti<NameValueHeaderValue> ("Pragma", NameValueHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response),
+				HeaderInfo.CreateMultiList<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),

+ 2 - 2
mcs/class/System.Net.Http/System.Net.Http.Headers/MediaTypeHeaderValue.cs

@@ -150,7 +150,7 @@ namespace System.Net.Http.Headers
 
 			switch (token.Value.Kind) {
 			case Token.Type.SeparatorSemicolon:
-				if (!NameValueHeaderValue.ParseParameters (lexer, out parameters))
+				if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters))
 					return false;
 				break;
 			case Token.Type.End:
@@ -181,7 +181,7 @@ namespace System.Net.Http.Headers
 
 			switch (token.Value.Kind) {
 			case Token.Type.SeparatorSemicolon:
-				if (!NameValueHeaderValue.ParseParameters (lexer, out parameters))
+				if (!NameValueHeaderValue.TryParseParameters (lexer, out parameters))
 					return false;
 				break;
 			case Token.Type.End:

+ 13 - 3
mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueHeaderValue.cs

@@ -121,8 +121,18 @@ namespace System.Net.Http.Headers
 			throw new FormatException (input);
 		}
 
-		internal static bool ParseParameters (Lexer lexer, out List<NameValueHeaderValue> result)
+		internal static bool TryParseParameters (Lexer lexer, out List<NameValueHeaderValue> result)
 		{
+			return TryParseCollection (lexer, out result, Token.Type.SeparatorSemicolon);
+		}
+
+		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)
+		{		
 			var list = new List<NameValueHeaderValue> ();
 			result = null;
 
@@ -146,7 +156,7 @@ namespace System.Net.Http.Headers
 					t = lexer.Scan ();
 				}
 
-				if (t == Token.Type.SeparatorSemicolon || t == Token.Type.End) {
+				if (t == separator|| t == Token.Type.End) {
 					list.Add (new NameValueHeaderValue () {
 						Name = lexer.GetStringValue (attr),
 						value = value
@@ -155,7 +165,7 @@ namespace System.Net.Http.Headers
 					return false;
 				}
 
-			} while (t == Token.Type.SeparatorSemicolon);
+			} while (t == separator);
 
 			result = list;
 			return true;

+ 1 - 1
mcs/class/System.Net.Http/System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs

@@ -103,7 +103,7 @@ namespace System.Net.Http.Headers
 		public static bool TryParse (string input, out NameValueWithParametersHeaderValue parsedValue)
 		{
 			List<NameValueHeaderValue> values;
-			if (!ParseParameters (new Lexer (input), out values)) {
+			if (!TryParseParameters (new Lexer (input), out values)) {
 				parsedValue = null;
 				return false;
 			}

+ 1 - 1
mcs/class/System.Net.Http/System.Net.Http.Headers/TransferCodingHeaderValue.cs

@@ -125,7 +125,7 @@ namespace System.Net.Http.Headers
 
 			// Parameters parsing
 			if (t == Token.Type.SeparatorSemicolon) {
-				if (!NameValueHeaderValue.ParseParameters (lexer, out result.parameters))
+				if (!NameValueHeaderValue.TryParseParameters (lexer, out result.parameters))
 					return false;
 			} else if (t != Token.Type.End) {
 				return false;

+ 15 - 2
mcs/class/System.Net.Http/Test/System.Net.Http/HttpRequestMessageTest.cs

@@ -219,6 +219,12 @@ namespace MonoTests.System.Net.Http
 			} catch (FormatException) {
 			}
 
+			try {
+				headers.Add ("pragma", "nocache,RequestID=1,g=");
+ 				Assert.Fail ("pragma");
+			} catch (FormatException) {				
+			}
+
 			headers.Add ("accept", "audio/y");
 			headers.Add ("accept-charset", "achs");
 			headers.Add ("accept-encoding", "aenc");
@@ -226,7 +232,6 @@ namespace MonoTests.System.Net.Http
 			headers.Add ("expect", "exp");
 			headers.Add ("if-match", "\"v\"");
 			headers.Add ("if-none-match", "\"v2\"");
-			headers.Add ("pragma", "p");
 			headers.Add ("TE", "0.8");
 			headers.Add ("trailer", "value2");
 			headers.Add ("transfer-encoding", "ttt");
@@ -234,6 +239,7 @@ namespace MonoTests.System.Net.Http
 			headers.Add ("user-agent", "uaua");
 			headers.Add ("via", "prot v");
 			headers.Add ("warning", "4 ww \"t\"");
+			headers.Add ("pragma", "nocache,R=1,g");
 
 			Assert.IsTrue (headers.Accept.SequenceEqual (
 				new[] {
@@ -296,7 +302,6 @@ namespace MonoTests.System.Net.Http
 			Assert.IsTrue (headers.IfNoneMatch.SequenceEqual (new EntityTagHeaderValue[] { new EntityTagHeaderValue ("\"tag2\"", true), new EntityTagHeaderValue ("\"v2\"", false) }));
 			Assert.AreEqual (new DateTimeOffset (DateTime.Today), headers.IfRange.Date);
 			Assert.AreEqual (headers.MaxForwards, 0x15b3);
-			Assert.IsTrue (headers.Pragma.SequenceEqual (new NameValueHeaderValue[] { new NameValueHeaderValue ("name", "value"), new NameValueHeaderValue ("p", null) }));
 			Assert.AreEqual ("p", headers.ProxyAuthorization.Parameter);
 			Assert.AreEqual ("s", headers.ProxyAuthorization.Scheme);
 			Assert.AreEqual (5, headers.Range.Ranges.First ().From);
@@ -345,6 +350,14 @@ namespace MonoTests.System.Net.Http
 				}
 			));
 
+			Assert.IsTrue (headers.Pragma.SequenceEqual (
+				new[] {
+					new NameValueHeaderValue ("name", "value"),
+					new NameValueHeaderValue ("nocache", null),
+					new NameValueHeaderValue ("R", "1"),
+					new NameValueHeaderValue ("g", null)
+				}
+			));			
 		}
 
 		[Test]