Fixes xamarin-bug #8965: AllowHtmlAttribute ignored throwing exception on POST using...
authorPablo Ruiz Garcia <pablo.ruiz@gmail.com>
Sun, 16 Dec 2012 07:43:50 +0000 (08:43 +0100)
committerPablo Ruiz Garcia <pablo.ruiz@gmail.com>
Sun, 16 Dec 2012 07:43:50 +0000 (08:43 +0100)
Mono's implementation of Microsoft.Web.Infrastructure was incorrectly
applying validation over 'unvalidated collections' cause HttpRequest's
internal collection is being replaced by a new LazyWebROCollection
which internally performs validation inside it's Get() methods.

However, ValidationUtility.GetUnvalidatedCollections(..) should not
perform validation, as this is what MVC (when using AllowHtmlAttribute)
expects.

See: https://bugzilla.xamarin.com/show_bug.cgi?id=8965
License: This patch is under MIT/X11 license.

mcs/class/Microsoft.Web.Infrastructure/Microsoft.Web.Infrastructure.DynamicValidationHelper/ValidationUtility.cs

index 85d6ed2abaace06773b4c1acd8edf145d3bafcb5..5d40a5dde54458fb90d8cdb5830636cf05bfb35d 100644 (file)
@@ -36,6 +36,8 @@ namespace Microsoft.Web.Infrastructure.DynamicValidationHelper
        [EditorBrowsable (EditorBrowsableState.Never)]
        public static class ValidationUtility
        {
+               private const string UNVALIDATED_DATA_KEY = "__MWI_UNVALIDATED_DATA_KEY";
+
                [SecuritySafeCritical]
                public static void EnableDynamicValidation (HttpContext context)
                {
@@ -43,6 +45,13 @@ namespace Microsoft.Web.Infrastructure.DynamicValidationHelper
                        if (req == null)
                                return;
 
+                       // We migth get called more than once.. (weird, isnt it?)
+                       if (context.Items [UNVALIDATED_DATA_KEY] != null)
+                               return;
+
+                       // Store unvalidated values at context so we can get access them later.
+                       context.Items [UNVALIDATED_DATA_KEY] = new object [] { req.FormUnvalidated, req.QueryStringUnvalidated };
+
                        // Just to be safe, make sure it's on
                        req.ValidateInput ();
                        req.SetFormCollection (new LazyWebROCollection (RequestValidationSource.Form, req.FormUnvalidated), true);
@@ -71,15 +80,24 @@ namespace Microsoft.Web.Infrastructure.DynamicValidationHelper
                                HttpRequest req = context != null ? context.Request : null;
                                if (req == null)
                                        return null;
-                               return req.FormUnvalidated;
+                               return GetUnvalidatedCollection (context, 0) ?? req.FormUnvalidated;
                        };
 
                        queryStringGetter = () => {
                                HttpRequest req = context != null ? context.Request : null;
                                if (req == null)
                                        return null;
-                               return req.QueryStringUnvalidated;
+                               return GetUnvalidatedCollection (context, 1) ?? req.QueryStringUnvalidated;
                        };
                }
+
+               private static NameValueCollection GetUnvalidatedCollection (HttpContext context, int offset)
+               {
+                       if (context.Items [UNVALIDATED_DATA_KEY] == null)
+                               return null;
+
+                       var data = context.Items [UNVALIDATED_DATA_KEY] as object [];
+                       return data [offset] as NameValueCollection;
+               }
        }
 }