Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.Web.Mvc / System.Web.Mvc / AntiForgeryDataSerializer.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Diagnostics.CodeAnalysis;\r
16     using System.IO;\r
17     using System.Web;\r
18     using System.Web.Mvc.Resources;\r
19     using System.Web.UI;\r
20 \r
21     internal class AntiForgeryDataSerializer {\r
22 \r
23         private IStateFormatter _formatter;\r
24 \r
25         protected internal IStateFormatter Formatter {\r
26             get {\r
27                 if (_formatter == null) {\r
28                     _formatter = FormatterGenerator.GetFormatter();\r
29                 }\r
30                 return _formatter;\r
31             }\r
32             set {\r
33                 _formatter = value;\r
34             }\r
35         }\r
36 \r
37         private static HttpAntiForgeryException CreateValidationException(Exception innerException) {\r
38             return new HttpAntiForgeryException(MvcResources.AntiForgeryToken_ValidationFailed, innerException);\r
39         }\r
40 \r
41         public virtual AntiForgeryData Deserialize(string serializedToken) {\r
42             if (String.IsNullOrEmpty(serializedToken)) {\r
43                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "serializedToken");\r
44             }\r
45 \r
46             // call property getter outside try { } block so that exceptions bubble up for debugging\r
47             IStateFormatter formatter = Formatter;\r
48 \r
49             try {\r
50                 Triplet deserializedObj = (Triplet)formatter.Deserialize(serializedToken);\r
51                 return new AntiForgeryData() {\r
52                     Salt = (string)deserializedObj.First,\r
53                     Value = (string)deserializedObj.Second,\r
54                     CreationDate = (DateTime)deserializedObj.Third\r
55                 };\r
56             }\r
57             catch (Exception ex) {\r
58                 throw CreateValidationException(ex);\r
59             }\r
60         }\r
61 \r
62         public virtual string Serialize(AntiForgeryData token) {\r
63             if (token == null) {\r
64                 throw new ArgumentNullException("token");\r
65             }\r
66 \r
67             Triplet objToSerialize = new Triplet() {\r
68                 First = token.Salt,\r
69                 Second = token.Value,\r
70                 Third = token.CreationDate\r
71             };\r
72 \r
73             string serializedValue = Formatter.Serialize(objToSerialize);\r
74             return serializedValue;\r
75         }\r
76 \r
77         // See http://www.yoda.arachsys.com/csharp/singleton.html (fifth version - fully lazy) for the singleton pattern\r
78         // used here. We need to defer the call to TokenPersister.CreateFormatterGenerator() until we're actually\r
79         // servicing a request, else HttpContext.Current might be invalid in TokenPersister.CreateFormatterGenerator().\r
80         private static class FormatterGenerator {\r
81 \r
82             public static readonly Func<IStateFormatter> GetFormatter = TokenPersister.CreateFormatterGenerator();\r
83 \r
84             [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline",\r
85                 Justification = "This type must not be marked 'beforefieldinit'.")]\r
86             static FormatterGenerator() {\r
87             }\r
88 \r
89             // This type is very difficult to unit-test because Page.ProcessRequest() requires mocking\r
90             // much of the hosting environment. For now, we can perform functional tests of this feature.\r
91             private sealed class TokenPersister : PageStatePersister {\r
92                 private TokenPersister(Page page)\r
93                     : base(page) {\r
94                 }\r
95 \r
96                 public static Func<IStateFormatter> CreateFormatterGenerator() {\r
97                     // This code instantiates a page and tricks it into thinking that it's servicing\r
98                     // a postback scenario with encrypted ViewState, which is required to make the\r
99                     // StateFormatter properly decrypt data. Specifically, this code sets the\r
100                     // internal Page.ContainsEncryptedViewState flag.\r
101                     TextWriter writer = TextWriter.Null;\r
102                     HttpResponse response = new HttpResponse(writer);\r
103                     HttpRequest request = new HttpRequest("DummyFile.aspx", HttpContext.Current.Request.Url.ToString(), "__EVENTTARGET=true&__VIEWSTATEENCRYPTED=true");\r
104                     HttpContext context = new HttpContext(request, response);\r
105 \r
106                     Page page = new Page() {\r
107                         EnableViewStateMac = true,\r
108                         ViewStateEncryptionMode = ViewStateEncryptionMode.Always\r
109                     };\r
110                     page.ProcessRequest(context);\r
111 \r
112                     return () => new TokenPersister(page).StateFormatter;\r
113                 }\r
114 \r
115                 public override void Load() {\r
116                     throw new NotImplementedException();\r
117                 }\r
118 \r
119                 public override void Save() {\r
120                     throw new NotImplementedException();\r
121                 }\r
122             }\r
123         }\r
124 \r
125     }\r
126 }\r