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
|
// 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.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
using System.Web.SessionState;
using Microsoft.Web.Infrastructure.DynamicValidationHelper;
namespace System.Web.WebPages
{
public class WebPageHttpHandler : IHttpHandler, IRequiresSessionState
{
internal const string StartPageFileName = "_PageStart";
public static readonly string WebPagesVersionHeaderName = "X-AspNetWebPages-Version";
private static readonly List<string> _supportedExtensions = new List<string>();
internal static readonly string WebPagesVersion = GetVersionString();
private readonly WebPage _webPage;
private readonly Lazy<WebPageRenderingBase> _startPage;
public WebPageHttpHandler(WebPage webPage)
: this(webPage, new Lazy<WebPageRenderingBase>(() => System.Web.WebPages.StartPage.GetStartPage(webPage, StartPageFileName, GetRegisteredExtensions())))
{
}
internal WebPageHttpHandler(WebPage webPage, Lazy<WebPageRenderingBase> startPage)
{
if (webPage == null)
{
throw new ArgumentNullException("webPage");
}
_webPage = webPage;
_startPage = startPage;
}
public static bool DisableWebPagesResponseHeader { get; set; }
public virtual bool IsReusable
{
get { return false; }
}
internal WebPage RequestedPage
{
get { return _webPage; }
}
internal WebPageRenderingBase StartPage
{
get { return _startPage.Value; }
}
internal static void AddVersionHeader(HttpContextBase httpContext)
{
if (!DisableWebPagesResponseHeader)
{
httpContext.Response.AppendHeader(WebPagesVersionHeaderName, WebPagesVersion);
}
}
public static IHttpHandler CreateFromVirtualPath(string virtualPath)
{
return CreateFromVirtualPath(virtualPath, VirtualPathFactoryManager.Instance);
}
internal static IHttpHandler CreateFromVirtualPath(string virtualPath, IVirtualPathFactory virtualPathFactory)
{
// We will try to create a WebPage from our factory. If this fails, we assume that the virtual path maps to an IHttpHandler.
// Instantiate the page from the virtual path
WebPage page = virtualPathFactory.CreateInstance<WebPage>(virtualPath);
// If it's not a page, assume it's a regular handler
if (page == null)
{
return virtualPathFactory.CreateInstance<IHttpHandler>(virtualPath);
}
// Mark it as a 'top level' page (as opposed to a user control or master)
page.TopLevelPage = true;
// Give it its virtual path
page.VirtualPath = virtualPath;
// Assign it the object factory
page.VirtualPathFactory = virtualPathFactory;
// Return a handler over it
return new WebPageHttpHandler(page);
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "We don't want a property")]
public static ReadOnlyCollection<string> GetRegisteredExtensions()
{
return new ReadOnlyCollection<string>(_supportedExtensions);
}
private static string GetVersionString()
{
// DevDiv 216459:
// This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in
// medium trust. However, Assembly.FullName *is* accessible in medium trust.
return new AssemblyName(typeof(WebPageHttpHandler).Assembly.FullName).Version.ToString(2);
}
private static bool HandleError(Exception e)
{
// This method is similar to System.Web.UI.Page.HandleError
// Don't touch security exception
if (e is SecurityException)
{
return false;
}
throw new HttpUnhandledException(null, e);
}
internal static void GenerateSourceFilesHeader(WebPageContext context)
{
if (context.SourceFiles.Any())
{
var files = String.Join("|", context.SourceFiles);
// Since the characters in the value are files that may include characters outside of the ASCII set, header encoding as specified in RFC2047.
// =?<charset>?<encoding>?...?=
// In the following case, UTF8 is used with base64 encoding
var encodedText = "=?UTF-8?B?" + Convert.ToBase64String(Encoding.UTF8.GetBytes(files)) + "?=";
context.HttpContext.Response.AddHeader("X-SourceFiles", encodedText);
}
}
public virtual void ProcessRequest(HttpContext context)
{
// Dev10 bug 921943 - Plan9 should lower its permissions if operating in legacy CAS
SecurityUtil.ProcessInApplicationTrust(() =>
{
ProcessRequestInternal(context);
});
}
internal void ProcessRequestInternal(HttpContext context)
{
// enable dynamic validation for this request
ValidationUtility.EnableDynamicValidation(context);
context.Request.ValidateInput();
HttpContextBase contextBase = new HttpContextWrapper(context);
ProcessRequestInternal(contextBase);
}
internal void ProcessRequestInternal(HttpContextBase httpContext)
{
try
{
//WebSecurity.Context = contextBase;
AddVersionHeader(httpContext);
// This is also the point where a Plan9 request truly begins execution
// We call ExecutePageHierarchy on the requested page, passing in the possible initPage, so that
// the requested page can take care of the necessary push/pop context and trigger the call to
// the initPage.
_webPage.ExecutePageHierarchy(new WebPageContext { HttpContext = httpContext }, httpContext.Response.Output, StartPage);
if (ShouldGenerateSourceHeader(httpContext))
{
GenerateSourceFilesHeader(_webPage.PageContext);
}
}
catch (Exception e)
{
if (!HandleError(e))
{
throw;
}
}
}
public static void RegisterExtension(string extension)
{
// Note: we don't lock or check for duplicates because we only expect this method to be called during PreAppStart
_supportedExtensions.Add(extension);
}
internal static bool ShouldGenerateSourceHeader(HttpContextBase context)
{
return context.Request.IsLocal;
}
}
}
|