1 //------------------------------------------------------------------------------
2 // <copyright file="HttpContext.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 /*
8  * HttpContext class
9  *
10  * Copyright (c) 1999 Microsoft Corporation
11  */
12 
13 namespace System.Web {
14     using System;
15     using System.Collections;
16     using System.Collections.Generic;
17     using System.Collections.ObjectModel;
18     using System.ComponentModel;
19     using System.Configuration;
20     using System.Diagnostics.CodeAnalysis;
21     using System.Globalization;
22     using System.Linq;
23     using System.Net;
24     using System.Reflection;
25     using System.Runtime.CompilerServices;
26     using System.Runtime.Remoting.Messaging;
27     using System.Security.Permissions;
28     using System.Security.Principal;
29     using System.Threading;
30     using System.Threading.Tasks;
31     using System.Web.Caching;
32     using System.Web.Compilation;
33     using System.Web.Configuration;
34     using System.Web.Hosting;
35     using System.Web.Instrumentation;
36     using System.Web.Management;
37     using System.Web.Profile;
38     using System.Web.Security;
39     using System.Web.SessionState;
40     using System.Web.UI;
41     using System.Web.Util;
42     using System.Web.WebSockets;
43 
44 
45     /// <devdoc>
46     ///    <para>Encapsulates
47     ///       all HTTP-specific
48     ///       context used by the HTTP server to process Web requests.</para>
49     /// <para>System.Web.IHttpModules and System.Web.IHttpHandler instances are provided a
50     ///    reference to an appropriate HttpContext object. For example
51     ///    the Request and Response
52     ///    objects.</para>
53     /// </devdoc>
54     [SuppressMessage("Microsoft.Usage", "CA2302:FlagServiceProviders", Justification = "The service provider implementation is only for specific types which are not com interop types.")]
55     public sealed class HttpContext : IServiceProvider, IPrincipalContainer
56     {
57 
58         internal static readonly Assembly SystemWebAssembly = typeof(HttpContext).Assembly;
59         private static volatile bool s_eurlSet;
60         private static string s_eurl;
61 
62         private IHttpAsyncHandler  _asyncAppHandler;   // application as handler (not always HttpApplication)
63         private AsyncPreloadModeFlags _asyncPreloadModeFlags;
64         private bool               _asyncPreloadModeFlagsSet;
65         private HttpApplication    _appInstance;
66         private IHttpHandler       _handler;
67         [DoNotReset]
68         private HttpRequest        _request;
69         private HttpResponse       _response;
70         private HttpServerUtility  _server;
71         private Stack              _traceContextStack;
72         private TraceContext       _topTraceContext;
73         [DoNotReset]
74         private Hashtable          _items;
75         private ArrayList          _errors;
76         private Exception          _tempError;
77         private bool               _errorCleared;
78         [DoNotReset]
79         private IPrincipalContainer _principalContainer;
80         [DoNotReset]
81         internal ProfileBase       _Profile;
82         [DoNotReset]
83         private DateTime           _utcTimestamp;
84         [DoNotReset]
85         private HttpWorkerRequest  _wr;
86         private VirtualPath        _configurationPath;
87         internal bool              _skipAuthorization;
88         [DoNotReset]
89         private CultureInfo        _dynamicCulture;
90         [DoNotReset]
91         private CultureInfo        _dynamicUICulture;
92         private int                _serverExecuteDepth;
93         private Stack              _handlerStack;
94         private bool               _preventPostback;
95         private bool               _runtimeErrorReported;
96         private PageInstrumentationService _pageInstrumentationService = null;
97         private ReadOnlyCollection<string> _webSocketRequestedProtocols;
98 
99         // timeout support
100         [DoNotReset]
101         private CancellationTokenHelper _timeoutCancellationTokenHelper; // used for TimedOutToken
102 
103         private long       _timeoutStartTimeUtcTicks = -1; // should always be accessed atomically; -1 means uninitialized
104         private long       _timeoutTicks = -1; // should always be accessed atomically; -1 means uninitialized
105         private int        _timeoutState;   // 0=non-cancelable, 1=cancelable, -1=canceled
106         private DoubleLink _timeoutLink;    // link in the timeout's manager list
107         private bool       _threadAbortOnTimeout = true; // whether we should Thread.Abort() this thread when it times out
108         private Thread     _thread;
109 
110         // cached configuration
111         private CachedPathData _configurationPathData; // Cached data if _configurationPath != null
112         private CachedPathData _filePathData;   // Cached data of the file being requested
113 
114         // Sql Cache Dependency
115         private string _sqlDependencyCookie;
116 
117         // Session State
118         volatile SessionStateModule _sessionStateModule;
119         volatile bool               _delayedSessionState;   // Delayed session state item
120 
121         // non-compiled pages
122         private TemplateControl _templateControl;
123 
124         // integrated pipeline state
125 
126         // For the virtual Disposing / Disposed events
127         private SubscriptionQueue<Action<HttpContext>> _requestCompletedQueue;
128         [DoNotReset]
129         private SubscriptionQueue<IDisposable> _pipelineCompletedQueue;
130 
131         // keep synchronized with mgdhandler.hxx
132         private const int FLAG_NONE                          =   0x0;
133         private const int FLAG_CHANGE_IN_SERVER_VARIABLES    =   0x1;
134         private const int FLAG_CHANGE_IN_REQUEST_HEADERS     =   0x2;
135         private const int FLAG_CHANGE_IN_RESPONSE_HEADERS    =   0x4;
136         private const int FLAG_CHANGE_IN_USER_OBJECT         =   0x8;
137         private const int FLAG_SEND_RESPONSE_HEADERS         =  0x10;
138         private const int FLAG_RESPONSE_HEADERS_SENT         =  0x20;
139         internal const int FLAG_ETW_PROVIDER_ENABLED         =  0x40;
140         private const int FLAG_CHANGE_IN_RESPONSE_STATUS     =  0x80;
141 
142         private volatile NotificationContext _notificationContext;
143         private bool _isAppInitialized;
144         [DoNotReset]
145         private bool _isIntegratedPipeline;
146         private bool _finishPipelineRequestCalled;
147         [DoNotReset]
148         private bool _impersonationEnabled;
149 
150         internal bool HideRequestResponse;
151         internal volatile bool InIndicateCompletion;
152         internal volatile ThreadContext IndicateCompletionContext = null;
153         internal volatile Thread ThreadInsideIndicateCompletion = null;
154 
155 
156         // This field is a surrogate for the HttpContext object itself. Our HostExecutionContextManager
157         // shouldn't capture a reference to the HttpContext itself since these references could be long-lived,
158         // e.g. if they're captured by a call to ThreadPool.QueueUserWorkItem or a Timer. This would cause the
159         // associated HttpContext object graph to be long-lived, which would negatively affect performance.
160         // Instead we capture a reference to this 'Id' object, which allows the HostExecutionContextManager
161         // to compare the original captured HttpContext with the current HttpContext without actually
162         // holding on to the original HttpContext instance.
163         [DoNotReset]
164         internal readonly object ThreadContextId = new object();
165 
166         // synchronization context (for EAP / TAP models)
167         private AspNetSynchronizationContextBase _syncContext;
168 
169         // This field doesn't need to be volatile since it will only ever be written to by a single thread, and when that thread
170         // later reads the field it will be guaranteed non-null. We don't care what other threads see, since it will never be
171         // equal to Thread.CurrentThread for them regardless of whether those threads are seeing the latest value of this field.
172         // This field should not be marked [DoNotReset] since we want it to be cleared when WebSocket processing begins.
173         internal Thread _threadWhichStartedWebSocketTransition;
174 
175         // WebSocket state
176         [DoNotReset]
177         private WebSocketTransitionState _webSocketTransitionState; // see comments in WebSocketTransitionState.cs for detailed info on this enum
178         [DoNotReset]
179         private string _webSocketNegotiatedProtocol;
180 
181         // see comments on WebSocketInitStatus for what all of these codes mean
GetWebSocketInitStatus()182         private WebSocketInitStatus GetWebSocketInitStatus() {
183             IIS7WorkerRequest iis7wr =_wr as IIS7WorkerRequest;
184             if (iis7wr == null) {
185                 return WebSocketInitStatus.RequiresIntegratedMode;
186             }
187 
188             if (CurrentNotification <= RequestNotification.BeginRequest) {
189                 return WebSocketInitStatus.CannotCallFromBeginRequest;
190             }
191 
192             if (!iis7wr.IsWebSocketRequest()) {
193                 if (iis7wr.IsWebSocketModuleActive()) {
194                     return WebSocketInitStatus.NotAWebSocketRequest;
195                 }
196                 else {
197                     return WebSocketInitStatus.NativeModuleNotEnabled;
198                 }
199             }
200 
201             if (iis7wr.GetIsChildRequest()) {
202                 return WebSocketInitStatus.CurrentRequestIsChildRequest;
203             }
204 
205             return WebSocketInitStatus.Success;
206         }
207 
208         // Returns true if the request contained the initial WebSocket handshake
209         // and IIS's WebSocket module is active.
210         public bool IsWebSocketRequest {
211             get {
212                 // If AcceptWebSocketRequest has already been called and run to completion, then this
213                 // is obviously a WebSocket request and we can skip further checks (which might throw).
214                 if (IsWebSocketRequestUpgrading) {
215                     return true;
216                 }
217 
218                 switch (GetWebSocketInitStatus()) {
219                     case WebSocketInitStatus.RequiresIntegratedMode:
220                         throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
221 
222                     case WebSocketInitStatus.CannotCallFromBeginRequest:
223                         throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledDuringBeginRequest));
224 
225                     case WebSocketInitStatus.Success:
226                         return true;
227 
228                     default:
229                         return false;
230                 }
231             }
232         }
233 
234         // While unwinding an HTTP request this indicates if the developer
235         // told ASP.NET that they wanted to transition to a websocket request
236         public bool IsWebSocketRequestUpgrading {
237             get { return (WebSocketTransitionState >= WebSocketTransitionState.AcceptWebSocketRequestCalled); }
238         }
239 
240         internal bool HasWebSocketRequestTransitionStarted {
241             get { return WebSocketTransitionState >= WebSocketTransitionState.TransitionStarted; }
242         }
243 
244         internal bool HasWebSocketRequestTransitionCompleted {
245             get { return WebSocketTransitionState >= WebSocketTransitionState.TransitionCompleted; }
246         }
247 
248         internal WebSocketTransitionState WebSocketTransitionState {
249             get { return _webSocketTransitionState; }
250             private set { _webSocketTransitionState = value; }
251         }
252 
253         // Returns the ordered list of protocols requested by the client,
254         // or an empty collection if this wasn't a WebSocket request or there was no list present.
255         public IList<string> WebSocketRequestedProtocols {
256             get {
257                 if (IsWebSocketRequest) {
258                     if (_webSocketRequestedProtocols == null) {
259                         string rawHeaderValue = _wr.GetUnknownRequestHeader("Sec-WebSocket-Protocol");
260                         IList<string> requestedProtocols = SubProtocolUtil.ParseHeader(rawHeaderValue); // checks for invalid values
261                         _webSocketRequestedProtocols = new ReadOnlyCollection<string>(requestedProtocols ?? new string[0]);
262                     }
263                     return _webSocketRequestedProtocols;
264                 }
265                 else {
266                     // not a WebSocket request
267                     return null;
268                 }
269             }
270         }
271 
272         // Returns the negotiated protocol (sent from the server to the client) for a
273         // WebSocket request.
274         public string WebSocketNegotiatedProtocol {
275             get { return _webSocketNegotiatedProtocol; }
276         }
277 
AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc)278         public void AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc) {
279             AcceptWebSocketRequest(userFunc, null);
280         }
281 
282         [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc, AspNetWebSocketOptions options)283         public void AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc, AspNetWebSocketOptions options) {
284             // Begin argument & state checking
285 
286             // We throw different error codes depending on the check that failed. Things that are
287             // server configuration errors (WebSockets not enabled) or developer errors (called this
288             // method with bad parameters) result in an appropriate exception type. Things that are
289             // remote errors (e.g. bad parameters from the client) result in an HTTP 4xx.
290 
291             if (userFunc == null) {
292                 throw new ArgumentNullException("userFunc");
293             }
294 
295             if (IsWebSocketRequestUpgrading) {
296                 // this method cannot be called multiple times
297                 throw new InvalidOperationException(SR.GetString(SR.WebSockets_AcceptWebSocketRequestCanOnlyBeCalledOnce));
298             }
299 
300             // DevDiv #384514: Task<T> doesn't work correctly using the legacy SynchronizationContext setting. Since
301             // WebSockets operation requires correct Task<T> behavior, we should forbid using the feature when legacy
302             // mode is enabled.
303             SynchronizationContextUtil.ValidateModeForWebSockets();
304 
305             switch (GetWebSocketInitStatus()) {
306                 case WebSocketInitStatus.RequiresIntegratedMode:
307                     throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
308 
309                 case WebSocketInitStatus.CannotCallFromBeginRequest:
310                     throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledDuringBeginRequest));
311 
312                 case WebSocketInitStatus.NativeModuleNotEnabled:
313                     throw new PlatformNotSupportedException(SR.GetString(SR.WebSockets_WebSocketModuleNotEnabled));
314 
315                 case WebSocketInitStatus.NotAWebSocketRequest:
316                     throw new HttpException((int)HttpStatusCode.BadRequest, SR.GetString(SR.WebSockets_NotAWebSocketRequest));
317 
318                 case WebSocketInitStatus.CurrentRequestIsChildRequest:
319                     throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledDuringChildExecute));
320 
321                 case WebSocketInitStatus.Success:
322                     break;
323 
324                 default:
325                     // fallback error message - not a WebSocket request
326                     throw new HttpException(SR.GetString(SR.WebSockets_UnknownErrorWhileAccepting));
327             }
328 
329             if (CurrentNotification > RequestNotification.ExecuteRequestHandler) {
330                 // it is too late to call this method
331                 throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledAfterHandlerExecute));
332             }
333             // End argument & state checking
334 
335             IIS7WorkerRequest wr = (IIS7WorkerRequest)_wr;
336 
337             // Begin options checking and parsing
338             if (options != null && options.RequireSameOrigin) {
339                 if (!WebSocketUtil.IsSameOriginRequest(wr)) {
340                     // use Forbidden (HTTP 403) since it's not an authentication error; it's a usage error
341                     throw new HttpException((int)HttpStatusCode.Forbidden, SR.GetString(SR.WebSockets_OriginCheckFailed));
342                 }
343             }
344 
345             string subprotocol = null;
346             if (options != null && !String.IsNullOrEmpty(options.SubProtocol)) {
347                 // AspNetWebSocketOptions.set_SubProtocol() already checked that the provided value is valid
348                 subprotocol = options.SubProtocol;
349             }
350 
351             if (subprotocol != null) {
352                 IList<string> incomingProtocols = WebSocketRequestedProtocols;
353                 if (incomingProtocols == null || !incomingProtocols.Contains(subprotocol, StringComparer.Ordinal)) {
354                     // The caller requested a subprotocol that wasn't in the list of accepted protocols coming from the client.
355                     // This is disallowed by the WebSockets protocol spec, Sec. 5.2.2 (#2).
356                     throw new ArgumentException(SR.GetString(SR.WebSockets_SubProtocolCannotBeNegotiated, subprotocol), "options");
357                 }
358             }
359             // End options checking and parsing
360 
361             wr.AcceptWebSocket();
362 
363             // transition: Inactive -> AcceptWebSocketRequestCalled
364             TransitionToWebSocketState(WebSocketTransitionState.AcceptWebSocketRequestCalled);
365 
366             Response.StatusCode = (int)HttpStatusCode.SwitchingProtocols; // 101
367             if (subprotocol != null) {
368                 Response.AppendHeader("Sec-WebSocket-Protocol", subprotocol);
369                 _webSocketNegotiatedProtocol = subprotocol;
370             }
371             RootedObjects.WebSocketPipeline = new WebSocketPipeline(RootedObjects, this, userFunc, subprotocol);
372         }
373 
TransitionToWebSocketState(WebSocketTransitionState newState)374         internal void TransitionToWebSocketState(WebSocketTransitionState newState) {
375             // Make sure the state transition is happening in the correct order
376 #if DBG
377             WebSocketTransitionState expectedOldState = checked(newState - 1);
378             Debug.Assert(WebSocketTransitionState == expectedOldState, String.Format(CultureInfo.InvariantCulture, "Expected WebSocketTransitionState to be '{0}', but it was '{1}'.", expectedOldState, WebSocketTransitionState));
379 #endif
380 
381             WebSocketTransitionState = newState;
382             if (newState == Web.WebSocketTransitionState.TransitionStarted) {
383                 _threadWhichStartedWebSocketTransition = Thread.CurrentThread;
384             }
385         }
386 
387         internal bool DidCurrentThreadStartWebSocketTransition {
388             get {
389                 return _threadWhichStartedWebSocketTransition == Thread.CurrentThread;
390             }
391         }
392 
393         // helper that throws an exception if we have transitioned the current request to a WebSocket request
EnsureHasNotTransitionedToWebSocket()394         internal void EnsureHasNotTransitionedToWebSocket() {
395             if (HasWebSocketRequestTransitionCompleted) {
396                 throw new NotSupportedException(SR.GetString(SR.WebSockets_MethodNotAvailableDuringWebSocketProcessing));
397             }
398         }
399 
400         internal bool FirstRequest {get; set;}
401 
402         // session state support
403         private bool _requiresSessionStateFromHandler;
404         internal bool RequiresSessionState {
405             get {
406                 switch (SessionStateBehavior) {
407                     case SessionStateBehavior.Required:
408                     case SessionStateBehavior.ReadOnly:
409                         return true;
410                     case SessionStateBehavior.Disabled:
411                         return false;
412                     case SessionStateBehavior.Default:
413                     default:
414                         return _requiresSessionStateFromHandler;
415                 }
416             }
417         }
418 
419         private bool _readOnlySessionStateFromHandler;
420         internal bool ReadOnlySessionState {
421             get {
422                 switch (SessionStateBehavior) {
423                     case SessionStateBehavior.ReadOnly:
424                         return true;
425                     case SessionStateBehavior.Required:
426                     case SessionStateBehavior.Disabled:
427                         return false;
428                     case SessionStateBehavior.Default:
429                     default:
430                         return _readOnlySessionStateFromHandler;
431                 }
432             }
433         }
434         internal bool InAspCompatMode;
435 
436         private IHttpHandler _remapHandler = null;
437 
438         /// <include file='doc\HttpContext.uex' path='docs/doc[@for="HttpContext.HttpContext"]/*' />
439         /// <devdoc>
440         ///    <para>
441         ///       Initializes a new instance of the HttpContext class.
442         ///    </para>
443         /// </devdoc>
HttpContext(HttpRequest request, HttpResponse response)444         public HttpContext(HttpRequest request, HttpResponse response) {
445             Init(request, response);
446             request.Context = this;
447             response.Context = this;
448         }
449 
450 
451         /// <devdoc>
452         ///    <para>
453         ///       Initializes a new instance of the HttpContext class.
454         ///    </para>
455         /// </devdoc>
HttpContext(HttpWorkerRequest wr)456         public HttpContext(HttpWorkerRequest wr) {
457             _wr = wr;
458             Init(new HttpRequest(wr, this), new HttpResponse(wr, this));
459             _response.InitResponseWriter();
460         }
461 
462         // ctor used in HttpRuntime
HttpContext(HttpWorkerRequest wr, bool initResponseWriter)463         internal HttpContext(HttpWorkerRequest wr, bool initResponseWriter) {
464             _wr = wr;
465             Init(new HttpRequest(wr, this), new HttpResponse(wr, this));
466 
467             if (initResponseWriter)
468                 _response.InitResponseWriter();
469 
470             PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_EXECUTING);
471         }
472 
Init(HttpRequest request, HttpResponse response)473         private void Init(HttpRequest request, HttpResponse response) {
474             _request = request;
475             _response = response;
476             _utcTimestamp = DateTime.UtcNow;
477             _principalContainer = this;
478 
479             if (_wr is IIS7WorkerRequest) {
480                 _isIntegratedPipeline = true;
481             }
482 
483             if (!(_wr is System.Web.SessionState.StateHttpWorkerRequest))
484                 CookielessHelper.RemoveCookielessValuesFromPath(); // This ensures that the cookieless-helper is initialized and
485             // rewrites the path if the URI contains cookieless form-auth ticket, session-id, etc.
486 
487             Profiler p = HttpRuntime.Profile;
488             if (p != null && p.IsEnabled)
489                 _topTraceContext = new TraceContext(this);
490 
491             // rewrite path in order to remove "/eurl.axd/guid", if it was
492             // added to the URL by aspnet_filter.dll.
493             string eurl = GetEurl();
494             if (!String.IsNullOrEmpty(eurl)) {
495                 string path = request.Path;
496                 int idxStartEurl = path.Length - eurl.Length;
497                 bool hasTrailingSlash = (path[path.Length - 1] == '/');
498                 if (hasTrailingSlash) {
499                     idxStartEurl--;
500                 }
501                 if (idxStartEurl >= 0
502                     && StringUtil.Equals(path, idxStartEurl, eurl, 0, eurl.Length)) {
503                     // restore original URL
504                     int originalUrlLen = idxStartEurl;
505                     if (hasTrailingSlash) {
506                         originalUrlLen++;
507                     }
508                     string originalUrl = path.Substring(0, originalUrlLen);
509                     // Dev10 835901: We don't call HttpContext.RewritePath(path) because the
510                     // original path may contain '?' encoded as %3F, and RewritePath
511                     // would interpret what follows as the query string.  So instead, we
512                     // clear ConfigurationPath and call InternalRewritePath directly.
513                     ConfigurationPath = null;
514                     Request.InternalRewritePath(VirtualPath.Create(originalUrl), null, true);
515                 }
516             }
517         }
518 
519         // We have a feature that directs extensionless URLs
520         // into managed code by appending "/eurl.axd/guid" to the path.  On IIS 6.0,
521         // we restore the URL as soon as we get into managed code.  Here we  get the
522         // actual value of "/eurl.axd/guid" and remember it.
GetEurl()523         private string GetEurl() {
524             // only used on IIS 6.0
525             if (!(_wr is ISAPIWorkerRequestInProcForIIS6)
526                 || (_wr is ISAPIWorkerRequestInProcForIIS7)) {
527                 return null;
528             }
529 
530             string eurl = s_eurl;
531             if (eurl == null && !s_eurlSet) {
532                 try {
533                     IntPtr pBuffer = UnsafeNativeMethods.GetExtensionlessUrlAppendage();
534                     if (pBuffer != IntPtr.Zero) {
535                         eurl = StringUtil.StringFromWCharPtr(pBuffer, UnsafeNativeMethods.lstrlenW(pBuffer));
536                     }
537                 }
538                 catch {} // ignore all exceptions
539                 s_eurl = eurl;
540                 s_eurlSet = true;
541             }
542             return eurl;
543         }
544 
545         // Current HttpContext off the call context
546 #if DBG
SetDebugAssertOnAccessToCurrent(bool doAssert)547         internal static void SetDebugAssertOnAccessToCurrent(bool doAssert) {
548             if (doAssert) {
549                 CallContext.SetData("__ContextAssert", String.Empty);
550             }
551             else {
552                 CallContext.SetData("__ContextAssert", null);
553             }
554         }
555 
556         private static bool NeedDebugAssertOnAccessToCurrent {
557             get {
558                 return (CallContext.GetData("__ContextAssert") != null);
559             }
560         }
561 #endif
562 
563         /// <devdoc>
564         ///    <para>Returns the current HttpContext object.</para>
565         /// </devdoc>
566         public static HttpContext Current {
567             get {
568 #if DBG
569                 if (NeedDebugAssertOnAccessToCurrent) {
570                     Debug.Assert(ContextBase.Current != null);
571                 }
572 #endif
573                 return ContextBase.Current as HttpContext;
574             }
575 
576             set {
577                 ContextBase.Current = value;
578             }
579         }
580 
581         //
582         //  Root / unroot for the duration of async operation
583         //  These are only used for the classic pipeline. The integrated pipeline uses a different rooting mechanism.
584         //
585 
586         private IntPtr _rootedPtr;
587 
588         [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
Root()589         internal void Root() {
590             _rootedPtr = GCUtil.RootObject(this);
591         }
592 
Unroot()593         internal void Unroot() {
594             GCUtil.UnrootObject(_rootedPtr);
595             _rootedPtr = IntPtr.Zero;
596         }
597 
FinishPipelineRequest()598         internal void FinishPipelineRequest() {
599             if (!_finishPipelineRequestCalled) {
600                 _finishPipelineRequestCalled = true;
601                 HttpRuntime.FinishPipelineRequest(this);
602             }
603         }
604 
605         // This is a virtual event which occurs when the HTTP part of this request is winding down, e.g. after EndRequest
606         // but before the WebSockets pipeline kicks in. The HttpContext is still available for inspection and is provided
607         // as a parameter to the supplied callback.
608         [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = @"The normal event pattern doesn't work between HttpContext and HttpContextBase since the signatures differ.")]
AddOnRequestCompleted(Action<HttpContext> callback)609         public ISubscriptionToken AddOnRequestCompleted(Action<HttpContext> callback) {
610             if (callback == null) {
611                 throw new ArgumentNullException("callback");
612             }
613 
614             return _requestCompletedQueue.Enqueue(callback);
615         }
616 
RaiseOnRequestCompleted()617         internal void RaiseOnRequestCompleted() {
618             // The callbacks really shouldn't throw exceptions, but we have a catch block just in case.
619             // Since there's nobody else that can listen for these errors (the request is unwinding and
620             // user code will no longer run), we'll just log the error.
621             try {
622                 _requestCompletedQueue.FireAndComplete(action => action(this));
623             }
624             catch (Exception e) {
625                 WebBaseEvent.RaiseRuntimeError(e, this);
626             }
627             finally {
628                 // Dispose of TimedOutToken so that nobody tries using it after this point.
629                 DisposeTimedOutToken();
630             }
631         }
632 
633         // Allows an object's Dispose() method to be called when the pipeline part of this request is completed, e.g.
634         // after both the HTTP part and the WebSockets loop have completed. The HttpContext is not available for
635         // inspection, and HttpContext.Current will be null.
636         [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
DisposeOnPipelineCompleted(IDisposable target)637         public ISubscriptionToken DisposeOnPipelineCompleted(IDisposable target) {
638             if (target == null) {
639                 throw new ArgumentNullException("target");
640             }
641 
642             if (RootedObjects != null) {
643                 // integrated pipeline
644                 return RootedObjects.DisposeOnPipelineCompleted(target);
645             }
646             else {
647                 // classic pipeline
648                 return _pipelineCompletedQueue.Enqueue(target);
649             }
650         }
651 
RaiseOnPipelineCompleted()652         internal void RaiseOnPipelineCompleted() {
653             // The callbacks really shouldn't throw exceptions, but we have a catch block just in case.
654             // Since there's nobody else that can listen for these errors (the request is unwinding and
655             // user code will no longer run), we'll just log the error.
656             try {
657                 _pipelineCompletedQueue.FireAndComplete(disposable => disposable.Dispose());
658             }
659             catch (Exception e) {
660                 WebBaseEvent.RaiseRuntimeError(e, null);
661             }
662         }
663 
ValidatePath()664         internal void ValidatePath() {
665             CachedPathData pathData = GetConfigurationPathData();
666             pathData.ValidatePath(_request.PhysicalPathInternal);
667         }
668 
669 
670         // IServiceProvider implementation
671 
672         /// <internalonly/>
IServiceProvider.GetService(Type service)673         Object IServiceProvider.GetService(Type service) {
674             Object obj;
675 
676             if (service == typeof(HttpWorkerRequest)) {
677                 InternalSecurityPermissions.UnmanagedCode.Demand();
678                 obj = _wr;
679             }
680             else if (service == typeof(HttpRequest))
681                 obj = Request;
682             else if (service == typeof(HttpResponse))
683                 obj = Response;
684             else if (service == typeof(HttpApplication))
685                 obj = ApplicationInstance;
686             else if (service == typeof(HttpApplicationState))
687                 obj = Application;
688             else if (service == typeof(HttpSessionState))
689                 obj = Session;
690             else if (service == typeof(HttpServerUtility))
691                 obj = Server;
692             else
693                 obj = null;
694 
695             return obj;
696         }
697 
698         //
699         // Async app handler is remembered for the duration of execution of the
700         // request when application happens to be IHttpAsyncHandler. It is needed
701         // for HttpRuntime to remember the object on which to call OnEndRequest.
702         //
703         // The assumption is that application is a IHttpAsyncHandler, not always
704         // HttpApplication.
705         //
706         internal IHttpAsyncHandler AsyncAppHandler {
707             get { return _asyncAppHandler; }
708             set { _asyncAppHandler = value; }
709         }
710 
711         public AsyncPreloadModeFlags AsyncPreloadMode {
712             get {
713                 if (!_asyncPreloadModeFlagsSet) {
714                     _asyncPreloadModeFlags = RuntimeConfig.GetConfig(this).HttpRuntime.AsyncPreloadMode;
715                     _asyncPreloadModeFlagsSet = true;
716                 }
717                 return _asyncPreloadModeFlags;
718             }
719             set {
720                 _asyncPreloadModeFlags = value;
721                 _asyncPreloadModeFlagsSet = true;
722             }
723         }
724 
725         // If this flag is not set, the AspNetSynchronizationContext associated with this request will throw
726         // exceptions when it detects the application misusing the async API. This can occur if somebody
727         // tries to call SynchronizationContext.Post / OperationStarted / etc. during a part of the
728         // pipeline where we weren't expecting asynchronous work to take place, if there is still
729         // outstanding asynchronous work when an asynchronous module or handler signals completion, etc.
730         // It is meant as a safety net to let developers know early on when they're writing async code
731         // which doesn't fit our expected patterns and where that code likely has negative side effects.
732         //
733         // This flag is respected only by AspNetSynchronizationContext; it has no effect when the
734         // legacy sync context is in use.
735         [EditorBrowsable(EditorBrowsableState.Advanced)]
736         public bool AllowAsyncDuringSyncStages {
737             get {
738                 return SyncContext.AllowAsyncDuringSyncStages;
739             }
740             set {
741                 SyncContext.AllowAsyncDuringSyncStages = value;
742             }
743         }
744 
745         /// <devdoc>
746         ///    <para>Retrieves a reference to the application object for the current Http request.</para>
747         /// </devdoc>
748         public HttpApplication ApplicationInstance {
749             get {
750                 return _appInstance;
751             }
752             set {
753                 // For integrated pipeline, once this is set to a non-null value, it can only be set to null.
754                 // The setter should never have been made public.  It probably happened in 1.0, before it was possible
755                 // to have getter and setter with different accessibility.
756                 if (_isIntegratedPipeline && _appInstance != null && value != null) {
757                     throw new InvalidOperationException(SR.GetString(SR.Application_instance_cannot_be_changed));
758                 }
759                 else {
760                     _appInstance = value;
761 
762                     // Use HttpApplication instance custom allocator provider
763                     if (_isIntegratedPipeline) {
764                         // The provider allows null - everyone should fallback to default implementation
765                         IAllocatorProvider allocator = _appInstance != null ? _appInstance.AllocatorProvider : null;
766 
767                         _response.SetAllocatorProvider(allocator);
768                         ((IIS7WorkerRequest)_wr).AllocatorProvider = allocator;
769                     }
770                 }
771             }
772         }
773 
774 
775         /// <devdoc>
776         ///    <para>
777         ///       Retrieves a reference to the application object for the current
778         ///       Http request.
779         ///    </para>
780         /// </devdoc>
781         public HttpApplicationState Application {
782             get { return HttpApplicationFactory.ApplicationState; }
783         }
784 
785 
786         // flag to suppress use of custom HttpEncoder registered in web.config
787         // for example, yellow error pages should use the default encoder rather than a custom encoder
788         internal bool DisableCustomHttpEncoder {
789             get;
790             set;
791         }
792 
793 
794         /// <devdoc>
795         ///    <para>
796         ///       Retrieves or assigns a reference to the <see cref='System.Web.IHttpHandler'/>
797         ///       object for the current request.
798         ///    </para>
799         /// </devdoc>
800         public IHttpHandler Handler {
801             get { return _handler;}
802             set {
803                 _handler = value;
804                 _requiresSessionStateFromHandler = false;
805                 _readOnlySessionStateFromHandler = false;
806                 InAspCompatMode = false;
807                 if (_handler != null) {
808                     if (_handler is IRequiresSessionState) {
809                         _requiresSessionStateFromHandler = true;
810                     }
811                     if (_handler is IReadOnlySessionState) {
812                         _readOnlySessionStateFromHandler = true;
813                     }
814                     Page page = _handler as Page;
815                     if (page != null && page.IsInAspCompatMode) {
816                         InAspCompatMode = true;
817                     }
818                 }
819             }
820         }
821 
822 
823         /// <devdoc>
824         ///    <para>
825         ///       Retrieves or assigns a reference to the <see cref='System.Web.IHttpHandler'/>
826         ///       object for the previous handler;
827         ///    </para>
828         /// </devdoc>
829 
830         public IHttpHandler PreviousHandler {
831             get {
832                 if (_handlerStack == null || _handlerStack.Count == 0)
833                     return null;
834 
835                 return (IHttpHandler)_handlerStack.Peek();
836             }
837         }
838 
839 
840         /// <devdoc>
841         ///    <para>
842         ///       Retrieves or assigns a reference to the <see cref='System.Web.IHttpHandler'/>
843         ///       object for the current executing handler;
844         ///    </para>
845         /// </devdoc>
846         private IHttpHandler _currentHandler = null;
847 
848         public IHttpHandler CurrentHandler {
849             get {
850                 if (_currentHandler == null)
851                     _currentHandler = _handler;
852 
853                 return _currentHandler;
854             }
855         }
856 
RestoreCurrentHandler()857         internal void RestoreCurrentHandler() {
858             _currentHandler = (IHttpHandler)_handlerStack.Pop();
859         }
860 
SetCurrentHandler(IHttpHandler newtHandler)861         internal void SetCurrentHandler(IHttpHandler newtHandler) {
862             if (_handlerStack == null) {
863                 _handlerStack = new Stack();
864             }
865             _handlerStack.Push(CurrentHandler);
866 
867             _currentHandler = newtHandler;
868         }
869 
870         /// <devdoc>
871         ///    <para>
872         ///       Set custom mapping handler processing the request <see cref='System.Web.IHttpHandler'/>
873         ///    </para>
874         /// </devdoc>
RemapHandler(IHttpHandler handler)875         public void RemapHandler(IHttpHandler handler) {
876             EnsureHasNotTransitionedToWebSocket();
877 
878             IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
879 
880             if (wr != null) {
881                 // Remap handler not allowed after ResolveRequestCache notification
882                 if (_notificationContext.CurrentNotification >= RequestNotification.MapRequestHandler) {
883                     throw new InvalidOperationException(SR.GetString(SR.Invoke_before_pipeline_event, "HttpContext.RemapHandler", "HttpApplication.MapRequestHandler"));
884                 }
885 
886                 string handlerTypeName = null;
887                 string handlerName = null;
888 
889                 if (handler != null) {
890                     Type handlerType = handler.GetType();
891 
892                     handlerTypeName = handlerType.AssemblyQualifiedName;
893                     handlerName = handlerType.FullName;
894                 }
895 
896                 wr.SetRemapHandler(handlerTypeName, handlerName);
897             }
898 
899             _remapHandler = handler;
900         }
901 
902         internal IHttpHandler RemapHandlerInstance {
903             get {
904                 return _remapHandler;
905             }
906         }
907 
908         /// <devdoc>
909         ///    <para>
910         ///       Retrieves a reference to the target <see cref='System.Web.HttpRequest'/>
911         ///       object for the current request.
912         ///    </para>
913         /// </devdoc>
914         public HttpRequest Request {
915             get {
916                  if (HideRequestResponse)
917                     throw new HttpException(SR.GetString(SR.Request_not_available));
918                 return _request;
919             }
920         }
921 
922 
923         /// <devdoc>
924         ///    <para>
925         ///       Retrieves a reference to the <see cref='System.Web.HttpResponse'/>
926         ///       object for the current response.
927         ///    </para>
928         /// </devdoc>
929         public HttpResponse Response {
930             get {
931                 if (HideRequestResponse || HasWebSocketRequestTransitionCompleted)
932                     throw new HttpException(SR.GetString(SR.Response_not_available));
933                 return _response;
934             }
935         }
936 
937 
938         internal IHttpHandler TopHandler {
939             get {
940                 if (_handlerStack == null) {
941                     return _handler;
942                 }
943                 object[] handlers = _handlerStack.ToArray();
944                 if (handlers == null || handlers.Length == 0) {
945                     return _handler;
946                 }
947                 return (IHttpHandler)handlers[handlers.Length - 1];
948             }
949         }
950 
951 
952         /// <devdoc>
953         /// <para>Retrieves a reference to the <see cref='System.Web.TraceContext'/> object for the current
954         ///    response.</para>
955         /// </devdoc>
956         public TraceContext Trace {
957             get {
958                 if (_topTraceContext == null)
959                     _topTraceContext = new TraceContext(this);
960                 return _topTraceContext;
961             }
962         }
963 
964         internal bool TraceIsEnabled {
965             get {
966                 if (_topTraceContext == null)
967                     return false;
968 
969                 return _topTraceContext.IsEnabled;
970             }
971             set {
972                 if (value)
973                     _topTraceContext = new TraceContext(this);
974             }
975 
976         }
977 
978 
979 
980         /// <devdoc>
981         ///    <para>
982         ///       Retrieves a key-value collection that can be used to
983         ///       build up and share data between an <see cref='System.Web.IHttpModule'/> and an <see cref='System.Web.IHttpHandler'/>
984         ///       during a
985         ///       request.
986         ///    </para>
987         /// </devdoc>
988         public IDictionary Items {
989             get {
990                 if (_items == null)
991                     _items = new Hashtable();
992 
993                 return _items;
994             }
995         }
996 
997 
998         /// <devdoc>
999         ///    <para>
1000         ///       Gets a reference to the <see cref='System.Web.SessionState'/> instance for the current request.
1001         ///    </para>
1002         /// </devdoc>
1003         public HttpSessionState Session {
1004             get {
1005                 if (HasWebSocketRequestTransitionCompleted) {
1006                     // Session is unavailable at this point
1007                     return null;
1008                 }
1009 
1010                 if (_delayedSessionState) {
1011                     lock (this) {
1012                         if (_delayedSessionState) {
1013                             Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null");
1014 
1015                             // If it's not null, it means we have a delayed session state item
1016                             _sessionStateModule.InitStateStoreItem(true);
1017                             _delayedSessionState = false;
1018                         }
1019                     }
1020                 }
1021 
1022                 return(HttpSessionState)Items[SessionStateUtility.SESSION_KEY];
1023             }
1024         }
1025 
1026         [MethodImpl(MethodImplOptions.NoInlining)]
EnsureSessionStateIfNecessary()1027         internal void EnsureSessionStateIfNecessary() {
1028             if (_sessionStateModule == null)
1029             {
1030                 // If _sessionStateModule is null, we wouldn't be able to call
1031                 // _sessionStateModule.EnsureStateStoreItemLocked(), so we return here.
1032                 // _sessionStateModule could be null in the following cases,
1033                 // 1. No session state acquired.
1034                 // 2. HttpResponse.Flush() happens after session state being released.
1035                 // 3. The session state module in use is not System.Web.SessionState.SessionStateModule.
1036                 //
1037                 // This method is for the in-framework SessionStateModule only.
1038                 //  OOB SessionStateModule can achieve this by using HttpResponse.AddOnSendingHeaders.
1039                 return;
1040             }
1041 
1042             HttpSessionState session = (HttpSessionState)Items[SessionStateUtility.SESSION_KEY];
1043 
1044             if (session != null &&                                 // The session has been initiated
1045                 session.Count > 0 &&                               // The session state is used
1046                 !string.IsNullOrEmpty(session.SessionID)) {        // Ensure the session Id is valid - it will force to create new if didn't exist
1047                 _sessionStateModule.EnsureStateStoreItemLocked();  // Lock the item if in use
1048             }
1049         }
1050 
1051 
AddHttpSessionStateModule(SessionStateModule module, bool delayed)1052         internal void AddHttpSessionStateModule(SessionStateModule module, bool delayed) {
1053             if (_sessionStateModule != null && _sessionStateModule != module) {
1054                 throw new HttpException(SR.GetString(SR.Cant_have_multiple_session_module));
1055             }
1056             _sessionStateModule = module;
1057             _delayedSessionState = delayed;
1058         }
1059 
RemoveHttpSessionStateModule()1060         internal void RemoveHttpSessionStateModule() {
1061             _delayedSessionState = false;
1062             _sessionStateModule = null;
1063         }
1064 
1065 
1066         /// <devdoc>
1067         ///    <para>
1068         ///       Gets a reference to the <see cref='System.Web.HttpServerUtility'/>
1069         ///       for the current
1070         ///       request.
1071         ///    </para>
1072         /// </devdoc>
1073         public HttpServerUtility Server {
1074             get {
1075                 // create only on demand
1076                 if (_server == null)
1077                     _server = new HttpServerUtility(this);
1078                 return _server;
1079             }
1080         }
1081 
1082         // if the context has an error, report it, but only one time
ReportRuntimeErrorIfExists(ref RequestNotificationStatus status)1083         internal void ReportRuntimeErrorIfExists(ref RequestNotificationStatus status) {
1084             Exception e = Error;
1085 
1086             if (e == null || _runtimeErrorReported) {
1087                 return;
1088             }
1089 
1090             // WOS 1921799: custom errors don't work in integrated mode if there's an initialization exception
1091             if (_notificationContext != null && CurrentModuleIndex == -1) {
1092                 try {
1093                     IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
1094                     if (Request.QueryString["aspxerrorpath"] != null
1095                         && wr != null
1096                         && String.IsNullOrEmpty(wr.GetManagedHandlerType())
1097                         && wr.GetCurrentModuleName() == PipelineRuntime.InitExceptionModuleName) {
1098                         status = RequestNotificationStatus.Continue;   // allow non-managed handler to execute request
1099                         return;
1100                     }
1101                 }
1102                 catch {
1103                 }
1104             }
1105 
1106             _runtimeErrorReported = true;
1107 
1108             if (HttpRuntime.AppOfflineMessage != null) {
1109                 try {
1110                     // report app offline error
1111                     Response.TrySkipIisCustomErrors = true;
1112                     HttpRuntime.ReportAppOfflineErrorMessage(Response, HttpRuntime.AppOfflineMessage);
1113 
1114                 }
1115                 catch {
1116                 }
1117             }
1118             else {
1119                 // report error exception
1120                 using (new DisposableHttpContextWrapper(this)) {
1121 
1122                     // if the custom encoder throws, it might interfere with returning error information
1123                     // to the client, so we force use of the default encoder
1124                     DisableCustomHttpEncoder = true;
1125 
1126                     // when application is on UNC share the code below must
1127                     // be run while impersonating the token given by IIS
1128                     using (new ApplicationImpersonationContext()) {
1129 
1130                         try {
1131                             try {
1132                                 // try to report error in a way that could possibly throw (a config exception)
1133                                 Response.ReportRuntimeError(e, true /*canThrow*/, false);
1134                             }
1135                             catch (Exception eReport) {
1136                                 // report the config error in a way that would not throw
1137                                 Response.ReportRuntimeError(eReport, false /*canThrow*/, false);
1138                             }
1139                         }
1140                         catch (Exception) {
1141                         }
1142                     }
1143                 }
1144             }
1145 
1146             status = RequestNotificationStatus.FinishRequest;
1147             return;
1148         }
1149 
1150         /// <devdoc>
1151         ///    <para>
1152         ///       Gets the
1153         ///       first error (if any) accumulated during request processing.
1154         ///    </para>
1155         /// </devdoc>
1156         public Exception Error {
1157             get {
1158                 if (_tempError != null)
1159                     return _tempError;
1160                 if (_errors == null || _errors.Count == 0 || _errorCleared)
1161                     return null;
1162                 return (Exception)_errors[0];
1163             }
1164         }
1165 
1166         //
1167         // Temp error (yet to be caught on app level)
1168         // to be reported as Server.GetLastError() but could be cleared later
1169         //
1170         internal Exception TempError {
1171             get { return _tempError; }
1172             set { _tempError = value; }
1173         }
1174 
1175 
1176         /// <devdoc>
1177         ///    <para>
1178         ///       An array (collection) of errors accumulated while processing a
1179         ///       request.
1180         ///    </para>
1181         /// </devdoc>
1182         public Exception[] AllErrors {
1183             get {
1184                 int n = (_errors != null) ? _errors.Count : 0;
1185 
1186                 if (n == 0)
1187                     return null;
1188 
1189                 Exception[] errors = new Exception[n];
1190                 _errors.CopyTo(0, errors, 0, n);
1191                 return errors;
1192             }
1193         }
1194 
1195 
1196         /// <devdoc>
1197         ///    <para>
1198         ///       Registers an error for the current request.
1199         ///    </para>
1200         /// </devdoc>
AddError(Exception errorInfo)1201         public void AddError(Exception errorInfo) {
1202             if (_errors == null)
1203                 _errors = new ArrayList();
1204 
1205             _errors.Add(errorInfo);
1206 
1207             if (_isIntegratedPipeline && _notificationContext != null) {
1208                 // set the error on the current notification context
1209                 _notificationContext.Error = errorInfo;
1210             }
1211         }
1212 
1213 
1214         /// <devdoc>
1215         ///    <para>
1216         ///       Clears all errors for the current request.
1217         ///    </para>
1218         /// </devdoc>
ClearError()1219         public void ClearError() {
1220             if (_tempError != null)
1221                 _tempError = null;
1222             else
1223                 _errorCleared = true;
1224 
1225             if (_isIntegratedPipeline && _notificationContext != null) {
1226                 // clear the error on the current notification context
1227                 _notificationContext.Error = null;
1228             }
1229         }
1230 
1231 
1232         /// <devdoc>
1233         ///    <para>
1234         ///       IPrincipal security information.
1235         ///    </para>
1236         /// </devdoc>
1237         public IPrincipal User {
1238             get { return _principalContainer.Principal; }
1239 
1240             [SecurityPermission(SecurityAction.Demand, ControlPrincipal=true)]
1241             set {
1242                 SetPrincipalNoDemand(value);
1243             }
1244         }
1245 
1246         IPrincipal IPrincipalContainer.Principal {
1247             get;
1248             set;
1249         }
1250 
1251         // route all internals call to the principal (that don't have luring attacks)
1252         // through this method so we can centralize reporting
1253         // Before this, some auth modules were assigning directly to _user
SetPrincipalNoDemand(IPrincipal principal, bool needToSetNativePrincipal)1254         internal void SetPrincipalNoDemand(IPrincipal principal, bool needToSetNativePrincipal) {
1255             _principalContainer.Principal = principal;
1256 
1257             // push changes through to native side
1258             if (needToSetNativePrincipal
1259                 && _isIntegratedPipeline
1260                 && _notificationContext.CurrentNotification == RequestNotification.AuthenticateRequest) {
1261 
1262                 IntPtr pManagedPrincipal = IntPtr.Zero;
1263                 IIS7WorkerRequest wr = (IIS7WorkerRequest)_wr;
1264                 wr.SetPrincipal(principal);
1265             }
1266         }
1267 
SetPrincipalNoDemand(IPrincipal principal)1268         internal void SetPrincipalNoDemand(IPrincipal principal) {
1269             SetPrincipalNoDemand(principal, true /*needToSetNativePrincipal*/);
1270         }
1271 
1272         [DoNotReset]
1273         internal bool _ProfileDelayLoad = false;
1274 
1275         public ProfileBase  Profile {
1276             get {
1277                 if (_Profile == null && _ProfileDelayLoad)
1278                     _Profile = ProfileBase.Create(Request.IsAuthenticated ? User.Identity.Name : Request.AnonymousID, Request.IsAuthenticated);
1279                 return _Profile;
1280             }
1281         }
1282 
1283         internal SessionStateBehavior SessionStateBehavior { get; set; }
1284 
1285         [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
1286           Justification = "An internal property already exists. This method does additional work.")]
SetSessionStateBehavior(SessionStateBehavior sessionStateBehavior)1287         public void SetSessionStateBehavior(SessionStateBehavior sessionStateBehavior) {
1288             if (_notificationContext != null && _notificationContext.CurrentNotification >= RequestNotification.AcquireRequestState) {
1289                 throw new InvalidOperationException(SR.GetString(SR.Invoke_before_pipeline_event, "HttpContext.SetSessionStateBehavior", "HttpApplication.AcquireRequestState"));
1290             }
1291 
1292             SessionStateBehavior = sessionStateBehavior;
1293         }
1294 
1295 
1296         public bool SkipAuthorization {
1297             get { return _skipAuthorization;}
1298 
1299             [SecurityPermission(SecurityAction.Demand, ControlPrincipal=true)]
1300             set {
1301                 SetSkipAuthorizationNoDemand(value, false);
1302             }
1303         }
1304 
SetSkipAuthorizationNoDemand(bool value, bool managedOnly)1305         internal void SetSkipAuthorizationNoDemand(bool value, bool managedOnly)
1306         {
1307             if (HttpRuntime.UseIntegratedPipeline
1308                 && !managedOnly
1309                 && value != _skipAuthorization) {
1310 
1311                 // For integrated mode, persist changes to SkipAuthorization
1312                 // in the IS_LOGIN_PAGE server variable.  When this server variable exists
1313                 // and the value is not "0", IIS skips authorization.
1314 
1315                 _request.SetSkipAuthorization(value);
1316             }
1317 
1318             _skipAuthorization = value;
1319         }
1320 
1321         // Pointer to the RootedObjects element, which contains information that needs to be flowed
1322         // between the HttpContext and the WebSocket, such as the current principal.
1323         [DoNotReset]
1324         private RootedObjects _rootedObjects;
1325 
1326         internal RootedObjects RootedObjects {
1327             get {
1328                 return _rootedObjects;
1329             }
1330             set {
1331                 // Sync the Principal between the containers
1332                 SwitchPrincipalContainer(value);
1333                 _rootedObjects = value;
1334             }
1335         }
1336 
SwitchPrincipalContainer(IPrincipalContainer newPrincipalContainer)1337         private void SwitchPrincipalContainer(IPrincipalContainer newPrincipalContainer) {
1338             if (newPrincipalContainer == null) {
1339                 newPrincipalContainer = this;
1340             }
1341 
1342             // Ensure new container contains the current principal
1343             IPrincipal currentPrincipal = _principalContainer.Principal;
1344             newPrincipalContainer.Principal = currentPrincipal;
1345             _principalContainer = newPrincipalContainer;
1346         }
1347 
1348         /// <devdoc>
1349         ///    <para>
1350         ///       Is this request in debug mode?
1351         ///    </para>
1352         /// </devdoc>
1353         public bool IsDebuggingEnabled {
1354             get {
1355                 try {
1356                     return CompilationUtil.IsDebuggingEnabled(this);
1357                 }
1358                 catch {
1359                     // in case of config errors don't throw
1360                     return false;
1361                 }
1362             }
1363         }
1364 
1365 
1366         /// <devdoc>
1367         ///    <para>
1368         ///       Is this custom error enabled for this request?
1369         ///    </para>
1370         /// </devdoc>
1371         public bool IsCustomErrorEnabled {
1372             get {
1373                 return CustomErrorsSection.GetSettings(this).CustomErrorsEnabled(_request);
1374             }
1375         }
1376 
1377         internal TemplateControl TemplateControl {
1378             get {
1379                 return _templateControl;
1380             }
1381             set {
1382                 _templateControl = value;
1383             }
1384         }
1385 
1386 
1387         /// <devdoc>
1388         ///    <para>Gets the initial timestamp of the current request.</para>
1389         /// </devdoc>
1390         public DateTime Timestamp {
1391             get { return _utcTimestamp.ToLocalTime();}
1392         }
1393 
1394         internal DateTime UtcTimestamp {
1395             get { return _utcTimestamp;}
1396         }
1397 
1398         internal HttpWorkerRequest WorkerRequest {
1399             get { return _wr;}
1400         }
1401 
1402 
1403         /// <devdoc>
1404         ///    <para>
1405         ///       Gets a reference to the System.Web.Cache.Cache object for the current request.
1406         ///    </para>
1407         /// </devdoc>
1408         public Cache Cache {
1409             get { return HttpRuntime.Cache;}
1410         }
1411 
1412         /// <summary>
1413         /// Gets a reference to the System.Web.Instrumentation.PageInstrumentationService instance for this request. Guaranteed not to be null (barring private reflection magic).
1414         /// </summary>
1415         public PageInstrumentationService PageInstrumentation {
1416             get {
1417                 if(_pageInstrumentationService == null) {
1418                     _pageInstrumentationService = new PageInstrumentationService();
1419                 }
1420                 return _pageInstrumentationService;
1421             }
1422         }
1423 
1424         /*
1425          * The virtual path used to get config settings.  This allows the user
1426          * to specify a non default config path, without having to pass it to every
1427          * configuration call.
1428          */
1429         internal VirtualPath ConfigurationPath {
1430             get {
1431                 if (_configurationPath == null)
1432                     _configurationPath = _request.FilePathObject;
1433 
1434                 return _configurationPath;
1435             }
1436 
1437             set {
1438                 _configurationPath = value;
1439                 _configurationPathData = null;
1440                 _filePathData = null;
1441             }
1442         }
1443 
GetFilePathData()1444         internal CachedPathData GetFilePathData() {
1445             if (_filePathData == null) {
1446                 _filePathData = CachedPathData.GetVirtualPathData(_request.FilePathObject, false);
1447             }
1448 
1449             return _filePathData;
1450         }
1451 
GetConfigurationPathData()1452         internal CachedPathData GetConfigurationPathData() {
1453             if (_configurationPath == null) {
1454                 return GetFilePathData();
1455             }
1456 
1457             //
1458             if (_configurationPathData == null) {
1459                 _configurationPathData = CachedPathData.GetVirtualPathData(_configurationPath, true);
1460             }
1461 
1462             return _configurationPathData;
1463         }
1464 
GetPathData(VirtualPath path)1465         internal CachedPathData GetPathData(VirtualPath path) {
1466             if (path != null) {
1467                 if (path.Equals(_request.FilePathObject)) {
1468                     return GetFilePathData();
1469                 }
1470 
1471                 if (_configurationPath != null && path.Equals(_configurationPath)) {
1472                     return GetConfigurationPathData();
1473                 }
1474             }
1475 
1476             return CachedPathData.GetVirtualPathData(path, false);
1477         }
1478 
FinishRequestForCachedPathData(int statusCode)1479         internal void FinishRequestForCachedPathData(int statusCode) {
1480             // Remove the cached path data for a file path if the first request for it
1481             // does not succeed due to a bad request. Otherwise we could be vulnerable
1482             // to a DOS attack.
1483             if (_filePathData != null && !_filePathData.CompletedFirstRequest) {
1484                 if (400 <= statusCode && statusCode < 500) {
1485                     CachedPathData.RemoveBadPathData(_filePathData);
1486                 }
1487                 else {
1488                     CachedPathData.MarkCompleted(_filePathData);
1489                 }
1490             }
1491         }
1492 
1493         /*
1494          * Uses the Config system to get the specified configuraiton
1495          */
1496         [Obsolete("The recommended alternative is System.Web.Configuration.WebConfigurationManager.GetWebApplicationSection in System.Web.dll. http://go.microsoft.com/fwlink/?linkid=14202")]
GetAppConfig(String name)1497         public static object GetAppConfig(String name) {
1498             return WebConfigurationManager.GetWebApplicationSection(name);
1499         }
1500 
1501         [Obsolete("The recommended alternative is System.Web.HttpContext.GetSection in System.Web.dll. http://go.microsoft.com/fwlink/?linkid=14202")]
GetConfig(String name)1502         public object GetConfig(String name) {
1503             return GetSection(name);
1504         }
1505 
GetSection(String sectionName)1506         public object GetSection(String sectionName) {
1507             if (HttpConfigurationSystem.UseHttpConfigurationSystem) {
1508                 return GetConfigurationPathData().ConfigRecord.GetSection(sectionName);
1509             }
1510             else {
1511                 return ConfigurationManager.GetSection(sectionName);
1512             }
1513         }
1514 
GetRuntimeConfig()1515         internal RuntimeConfig GetRuntimeConfig() {
1516             return GetConfigurationPathData().RuntimeConfig;
1517         }
1518 
GetRuntimeConfig(VirtualPath path)1519         internal RuntimeConfig GetRuntimeConfig(VirtualPath path) {
1520             return GetPathData(path).RuntimeConfig;
1521         }
1522 
RewritePath(String path)1523         public void RewritePath(String path) {
1524             RewritePath(path, true);
1525         }
1526 
1527         /*
1528          * Called by the URL rewrite module to modify the path for downstream modules
1529          */
1530 
1531         /// <devdoc>
1532         ///    <para>[To be supplied.]</para>
1533         /// </devdoc>
RewritePath(String path, bool rebaseClientPath)1534         public void RewritePath(String path, bool rebaseClientPath) {
1535             if (path == null)
1536                 throw new ArgumentNullException("path");
1537 
1538             // extract query string
1539             String qs = null;
1540             int iqs = path.IndexOf('?');
1541             if (iqs >= 0) {
1542                 qs = (iqs < path.Length-1) ? path.Substring(iqs+1) : String.Empty;
1543                 path = path.Substring(0, iqs);
1544             }
1545 
1546             // resolve relative path
1547             VirtualPath virtualPath = VirtualPath.Create(path);
1548             virtualPath = Request.FilePathObject.Combine(virtualPath);
1549 
1550             // disallow paths outside of app
1551             virtualPath.FailIfNotWithinAppRoot();
1552 
1553             // clear things that depend on path
1554             ConfigurationPath = null;
1555 
1556             // rewrite path on request
1557             Request.InternalRewritePath(virtualPath, qs, rebaseClientPath);
1558         }
1559 
1560 
1561         /// <devdoc>
1562         ///    <para>[To be supplied.]</para>
1563         /// </devdoc>
RewritePath(String filePath, String pathInfo, String queryString)1564         public void RewritePath(String filePath, String pathInfo, String queryString) {
1565             RewritePath(VirtualPath.CreateAllowNull(filePath), VirtualPath.CreateAllowNull(pathInfo),
1566                 queryString, false /*setClientFilePath*/);
1567         }
RewritePath(string filePath, string pathInfo, String queryString, bool setClientFilePath)1568         public void RewritePath(string filePath, string pathInfo, String queryString, bool setClientFilePath)
1569         {
1570             RewritePath(VirtualPath.CreateAllowNull(filePath), VirtualPath.CreateAllowNull(pathInfo), queryString, setClientFilePath);
1571         }
RewritePath(VirtualPath filePath, VirtualPath pathInfo, String queryString, bool setClientFilePath)1572         internal void RewritePath(VirtualPath filePath, VirtualPath pathInfo, String queryString, bool setClientFilePath) {
1573             EnsureHasNotTransitionedToWebSocket();
1574 
1575             if (filePath == null)
1576                 throw new ArgumentNullException("filePath");
1577 
1578             // resolve relative path
1579             filePath = Request.FilePathObject.Combine(filePath);
1580 
1581             // disallow paths outside of app
1582             filePath.FailIfNotWithinAppRoot();
1583 
1584             // clear things that depend on path
1585             ConfigurationPath = null;
1586 
1587             // rewrite path on request
1588             Request.InternalRewritePath(filePath, pathInfo, queryString, setClientFilePath);
1589         }
1590 
1591         internal CultureInfo DynamicCulture {
1592             get { return _dynamicCulture; }
1593             set { _dynamicCulture = value; }
1594         }
1595 
1596         internal CultureInfo DynamicUICulture {
1597             get { return _dynamicUICulture; }
1598             set { _dynamicUICulture = value; }
1599         }
1600 
GetGlobalResourceObject(string classKey, string resourceKey)1601         public static object GetGlobalResourceObject(string classKey, string resourceKey) {
1602             return GetGlobalResourceObject(classKey, resourceKey, null);
1603         }
1604 
GetGlobalResourceObject(string classKey, string resourceKey, CultureInfo culture)1605         public static object GetGlobalResourceObject(string classKey, string resourceKey, CultureInfo culture) {
1606             return ResourceExpressionBuilder.GetGlobalResourceObject(classKey, resourceKey, null, null, culture);
1607         }
1608 
GetLocalResourceObject(string virtualPath, string resourceKey)1609         public static object GetLocalResourceObject(string virtualPath, string resourceKey) {
1610             return GetLocalResourceObject(virtualPath, resourceKey, null);
1611         }
1612 
GetLocalResourceObject(string virtualPath, string resourceKey, CultureInfo culture)1613         public static object GetLocalResourceObject(string virtualPath, string resourceKey, CultureInfo culture) {
1614             IResourceProvider pageProvider = ResourceExpressionBuilder.GetLocalResourceProvider(
1615                 VirtualPath.Create(virtualPath));
1616             return ResourceExpressionBuilder.GetResourceObject(pageProvider, resourceKey, culture);
1617         }
1618 
1619         internal int ServerExecuteDepth {
1620             get { return _serverExecuteDepth; }
1621             set { _serverExecuteDepth = value; }
1622         }
1623 
1624         internal bool PreventPostback {
1625             get { return _preventPostback; }
1626             set { _preventPostback = value; }
1627         }
1628 
1629         //
1630         // Timeout support
1631         //
1632 
1633         internal Thread CurrentThread {
1634             get {
1635                 return _thread;
1636             }
1637             set {
1638                 _thread = value;
1639             }
1640         }
1641 
1642         // Property is thread-safe since needs to be accessed by RequestTimeoutManager in addition to
1643         // normal request threads.
1644         internal TimeSpan Timeout {
1645             get {
1646                 long ticks = EnsureTimeout();
1647                 return TimeSpan.FromTicks(ticks);
1648             }
1649 
1650             set {
1651                 Interlocked.Exchange(ref _timeoutTicks, value.Ticks);
1652             }
1653         }
1654 
1655         // Access via HttpRequest.TimedOutToken instead.
1656         internal CancellationToken TimedOutToken {
1657             get {
1658                 // If we are the first call site to observe the token, then create it in the non-canceled state.
1659                 CancellationTokenHelper helper = LazyInitializer.EnsureInitialized(ref _timeoutCancellationTokenHelper, () => new CancellationTokenHelper(canceled: false));
1660                 return helper.Token;
1661             }
1662         }
1663 
1664         /// <summary>
1665         /// Determines whether the ASP.NET runtime calls Thread.Abort() on the thread servicing this request when
1666         /// the request times out. Default value is 'true'.
1667         /// </summary>
1668         /// <remarks>
1669         /// Handlers and modules that are using Request.TimedOutToken to implement cooperative cancellation may
1670         /// wish to disable the rude Thread.Abort behavior that ASP.NET has historically performed when a request
1671         /// times out. This can help developers make sure that their g----ful cancellation + cleanup routines
1672         /// will run without interruption by ASP.NET.
1673         ///
1674         /// The rules for determining when a thread is aborted are somewhat complicated, so applications shouldn't
1675         /// try to depend on them. Currently, the behavior is:
1676         ///
1677         /// - The thread will be aborted at some point after Request.TimedOutToken is canceled. The abort might not
1678         ///   occur immediately afterward, as the "should Thread.Abort" timer is separate from the "should signal
1679         ///   the CancellationToken" timer.
1680         ///
1681         /// - We generally don't abort threads that are processing async modules or handlers. There are some
1682         ///   exceptions. E.g., during certain parts of the lifecycle for async WebForms pages, the thread can be
1683         ///   a candidate to be aborted when a timeout occurs.
1684         ///
1685         /// If a developer sets this property to 'false', ASP.NET will not automatically display a "Request timed
1686         /// out" YSOD when a timeout occurs. If this happens the application is responsible for setting the response
1687         /// content appropriately.
1688         /// </remarks>
1689         public bool ThreadAbortOnTimeout {
1690             get { return Volatile.Read(ref _threadAbortOnTimeout); }
1691             set { Volatile.Write(ref _threadAbortOnTimeout, value); }
1692         }
1693 
DisposeTimedOutToken()1694         private void DisposeTimedOutToken() {
1695             // If we are the first call site to observe the token, then create it in the disposed state.
1696             CancellationTokenHelper helper = LazyInitializer.EnsureInitialized(ref _timeoutCancellationTokenHelper, () => CancellationTokenHelper.StaticDisposed);
1697             helper.Dispose();
1698         }
1699 
EnsureTimeout()1700         internal long EnsureTimeout() {
1701             // Calls to Volatile.* are atomic, even for 64-bit fields.
1702             long ticks = Volatile.Read(ref _timeoutTicks);
1703             if (ticks == -1) {
1704                 // Only go to config if the value hasn't yet been initialized.
1705                 HttpRuntimeSection cfg = RuntimeConfig.GetConfig(this).HttpRuntime;
1706                 ticks = cfg.ExecutionTimeout.Ticks;
1707 
1708                 // If another thread already came in and initialized _timeoutTicks,
1709                 // return that value instead of the value we just read from config.
1710                 long originalTicks = Interlocked.CompareExchange(ref _timeoutTicks, ticks, -1);
1711                 if (originalTicks != -1) {
1712                     ticks = originalTicks;
1713                 }
1714             }
1715 
1716             return ticks;
1717         }
1718 
1719         internal DoubleLink TimeoutLink {
1720             get { return _timeoutLink;}
1721             set { _timeoutLink = value;}
1722         }
1723 
1724         /*
1725 
1726         Notes on the following 5 functions:
1727 
1728         Execution can be cancelled only during certain periods, when inside the catch
1729         block for ThreadAbortException.  These periods are marked with the value of
1730         _timeoutState of 1.
1731 
1732         There is potential [rare] race condition when the timeout thread would call
1733         thread.abort but the execution logic in the meantime escapes the catch block.
1734         To avoid such race conditions _timeoutState of -1 (cancelled) is introduced.
1735         The timeout thread sets _timeoutState to -1 before thread abort and the
1736         unwinding logic just waits for the exception in this case. The wait cannot
1737         be done in EndCancellablePeriod because the function is call from inside of
1738         a finally block and thus would wait indefinetely. That's why another function
1739         WaitForExceptionIfCancelled had been added.
1740 
1741         Originally _timeoutStartTime was set in BeginCancellablePeriod. However, that means
1742         we'll call UtcNow everytime we call ExecuteStep, which is too expensive. So to save
1743         CPU time we created a new method SetStartTime() which is called by the caller of
1744         ExecuteStep.
1745 
1746         */
1747 
BeginCancellablePeriod()1748         internal void BeginCancellablePeriod() {
1749             // It could be caused by an exception in OnThreadStart
1750             if (Volatile.Read(ref _timeoutStartTimeUtcTicks) == -1) {
1751                 SetStartTime();
1752             }
1753 
1754             Volatile.Write(ref _timeoutState, 1);
1755         }
1756 
SetStartTime()1757         internal void SetStartTime() {
1758             Interlocked.Exchange(ref _timeoutStartTimeUtcTicks, DateTime.UtcNow.Ticks);
1759         }
1760 
EndCancellablePeriod()1761         internal void EndCancellablePeriod() {
1762             Interlocked.CompareExchange(ref _timeoutState, 0, 1);
1763         }
1764 
WaitForExceptionIfCancelled()1765         internal void WaitForExceptionIfCancelled() {
1766             while (Volatile.Read(ref _timeoutState) == -1)
1767                 Thread.Sleep(100);
1768         }
1769 
1770         internal bool IsInCancellablePeriod {
1771             get { return (Volatile.Read(ref _timeoutState) == 1); }
1772         }
1773 
MustTimeout(DateTime utcNow)1774         internal Thread MustTimeout(DateTime utcNow) {
1775             // Note: The TimedOutToken is keyed off of the HttpContext creation time, not the most recent async
1776             // completion time (like the Thread.Abort logic later in this method).
1777 
1778             if (_utcTimestamp + Timeout < utcNow) {
1779                 // If we are the first call site to observe the token, then create it in the canceled state.
1780                 CancellationTokenHelper helper = LazyInitializer.EnsureInitialized(ref _timeoutCancellationTokenHelper, () => new CancellationTokenHelper(canceled: true));
1781                 helper.Cancel();
1782             }
1783 
1784             if (Volatile.Read(ref _timeoutState) == 1 && ThreadAbortOnTimeout) {  // fast check
1785                 long expirationUtcTicks = Volatile.Read(ref _timeoutStartTimeUtcTicks) + Timeout.Ticks; // don't care about overflow
1786                 if (expirationUtcTicks < utcNow.Ticks) {
1787                     // don't abort in debug mode
1788                     try {
1789                         if (CompilationUtil.IsDebuggingEnabled(this) || System.Diagnostics.Debugger.IsAttached)
1790                             return null;
1791                     }
1792                     catch {
1793                         // ignore config errors
1794                         return null;
1795                     }
1796 
1797                     // abort the thread only if in cancelable state, avoiding race conditions
1798                     // the caller MUST timeout if the return is true
1799                     if (Interlocked.CompareExchange(ref _timeoutState, -1, 1) == 1) {
1800                         if (_wr.IsInReadEntitySync) {
1801                             AbortConnection();
1802                         }
1803                         return _thread;
1804                     }
1805                 }
1806             }
1807 
1808             return null;
1809         }
1810 
1811         internal bool HasTimeoutExpired {
1812             get {
1813                 // Check if it is allowed to timeout
1814                 if (Volatile.Read(ref _timeoutState) != 1 || !ThreadAbortOnTimeout) {
1815                     return false;
1816                 }
1817 
1818                 // Check if the timeout has expired
1819                 long expirationUtcTicks = Volatile.Read(ref _timeoutStartTimeUtcTicks) + Timeout.Ticks; // don't care about overflow
1820                 if (expirationUtcTicks >= DateTime.UtcNow.Ticks) {
1821                     return false;
1822                 }
1823 
1824                 // Dont't timeout when in debug
1825                 try {
1826                     if (CompilationUtil.IsDebuggingEnabled(this) || System.Diagnostics.Debugger.IsAttached) {
1827                         return false;
1828                     }
1829                 }
1830                 catch {
1831                     // ignore config errors
1832                     return false;
1833                 }
1834 
1835                 return true;
1836             }
1837         }
1838 
1839         // call a delegate within cancellable period (possibly throwing timeout exception)
InvokeCancellableCallback(WaitCallback callback, Object state)1840         internal void InvokeCancellableCallback(WaitCallback callback, Object state) {
1841             if (IsInCancellablePeriod) {
1842                 // call directly
1843                 callback(state);
1844                 return;
1845             }
1846 
1847             try {
1848                 BeginCancellablePeriod();  // request can be cancelled from this point
1849 
1850                 try {
1851                     callback(state);
1852                 }
1853                 finally {
1854                     EndCancellablePeriod();  // request can be cancelled until this point
1855                 }
1856 
1857                 WaitForExceptionIfCancelled();  // wait outside of finally
1858             }
1859             catch (ThreadAbortException e) {
1860                 if (e.ExceptionState != null &&
1861                     e.ExceptionState is HttpApplication.CancelModuleException &&
1862                     ((HttpApplication.CancelModuleException)e.ExceptionState).Timeout) {
1863 
1864                     Thread.ResetAbort();
1865                     PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TIMED_OUT);
1866 
1867                     throw new HttpException(SR.GetString(SR.Request_timed_out),
1868                                         null, WebEventCodes.RuntimeErrorRequestAbort);
1869                 }
1870             }
1871         }
1872 
PushTraceContext()1873         internal void PushTraceContext() {
1874             if (_traceContextStack == null) {
1875                 _traceContextStack = new Stack();
1876             }
1877 
1878             // push current TraceContext on stack
1879             _traceContextStack.Push(_topTraceContext);
1880 
1881             // now make a new one for the top if necessary
1882             if (_topTraceContext != null) {
1883                 TraceContext tc = new TraceContext(this);
1884                 _topTraceContext.CopySettingsTo(tc);
1885                 _topTraceContext = tc;
1886             }
1887         }
1888 
PopTraceContext()1889         internal void PopTraceContext() {
1890             Debug.Assert(_traceContextStack != null);
1891             _topTraceContext = (TraceContext) _traceContextStack.Pop();
1892         }
1893 
RequestRequiresAuthorization()1894         internal bool RequestRequiresAuthorization()  {
1895 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
1896             // if current user is anonymous, then trivially, this page does not require authorization
1897             if (!User.Identity.IsAuthenticated)
1898                 return false;
1899 
1900             // Ask each of the authorization modules
1901             return
1902                 ( FileAuthorizationModule.RequestRequiresAuthorization(this) ||
1903                   UrlAuthorizationModule.RequestRequiresAuthorization(this)   );
1904 #else // !FEATURE_PAL
1905                 return false; // ROTORTODO
1906 #endif // !FEATURE_PAL
1907         }
1908 
CallISAPI(UnsafeNativeMethods.CallISAPIFunc iFunction, byte [] bufIn, byte [] bufOut)1909         internal int CallISAPI(UnsafeNativeMethods.CallISAPIFunc iFunction, byte [] bufIn, byte [] bufOut) {
1910 
1911             if (_wr == null || !(_wr is System.Web.Hosting.ISAPIWorkerRequest))
1912                 throw new HttpException(SR.GetString(SR.Cannot_call_ISAPI_functions));
1913 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
1914             return ((System.Web.Hosting.ISAPIWorkerRequest) _wr).CallISAPI(iFunction, bufIn, bufOut);
1915 #else // !FEATURE_PAL
1916                 throw new NotImplementedException ("ROTORTODO");
1917 #endif // !FEATURE_PAL
1918         }
1919 
SendEmptyResponse()1920         internal void SendEmptyResponse() {
1921 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
1922             if (_wr != null  && (_wr is System.Web.Hosting.ISAPIWorkerRequest))
1923                 ((System.Web.Hosting.ISAPIWorkerRequest) _wr).SendEmptyResponse();
1924 #endif // !FEATURE_PAL
1925         }
1926 
1927         private  CookielessHelperClass _CookielessHelper;
1928         internal CookielessHelperClass  CookielessHelper {
1929             get {
1930                 if (_CookielessHelper == null)
1931                     _CookielessHelper = new CookielessHelperClass(this);
1932                 return _CookielessHelper;
1933             }
1934         }
1935 
1936 
1937         // When a thread enters the pipeline, we may need to set the cookie in the CallContext.
ResetSqlDependencyCookie()1938         internal void ResetSqlDependencyCookie() {
1939             if (_sqlDependencyCookie != null) {
1940                 System.Runtime.Remoting.Messaging.CallContext.LogicalSetData(SqlCacheDependency.SQL9_OUTPUT_CACHE_DEPENDENCY_COOKIE, _sqlDependencyCookie);
1941             }
1942         }
1943 
1944         // When a thread leaves the pipeline, we may need to remove the cookie from the CallContext.
RemoveSqlDependencyCookie()1945         internal void RemoveSqlDependencyCookie() {
1946             if (_sqlDependencyCookie != null) {
1947                 System.Runtime.Remoting.Messaging.CallContext.LogicalSetData(SqlCacheDependency.SQL9_OUTPUT_CACHE_DEPENDENCY_COOKIE, null);
1948             }
1949         }
1950 
1951         internal string SqlDependencyCookie {
1952             get {
1953                 return _sqlDependencyCookie;
1954             }
1955 
1956             set {
1957                 _sqlDependencyCookie = value;
1958                 System.Runtime.Remoting.Messaging.CallContext.LogicalSetData(SqlCacheDependency.SQL9_OUTPUT_CACHE_DEPENDENCY_COOKIE, value);
1959             }
1960         }
1961 
1962         //
1963         // integrated pipeline related
1964         //
1965         internal NotificationContext NotificationContext {
1966             get { return _notificationContext; }
1967             set { _notificationContext = value; }
1968         }
1969 
1970         public RequestNotification CurrentNotification {
1971             get {
1972                 EnsureHasNotTransitionedToWebSocket();
1973 
1974                 if (!HttpRuntime.UseIntegratedPipeline) {
1975                     throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
1976                 }
1977 
1978                 return _notificationContext.CurrentNotification;
1979             }
1980             internal set {
1981                 if (!HttpRuntime.UseIntegratedPipeline) {
1982                     throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
1983                 }
1984 
1985                 _notificationContext.CurrentNotification = value;
1986             }
1987         }
1988 
1989         internal bool IsChangeInServerVars {
1990             get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_SERVER_VARIABLES) == FLAG_CHANGE_IN_SERVER_VARIABLES; }
1991         }
1992 
1993         internal bool IsChangeInRequestHeaders {
1994             get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_REQUEST_HEADERS) == FLAG_CHANGE_IN_REQUEST_HEADERS; }
1995         }
1996 
1997         internal bool IsChangeInResponseHeaders {
1998             get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_RESPONSE_HEADERS) == FLAG_CHANGE_IN_RESPONSE_HEADERS; }
1999         }
2000 
2001         internal bool IsChangeInResponseStatus {
2002             get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_RESPONSE_STATUS) == FLAG_CHANGE_IN_RESPONSE_STATUS; }
2003         }
2004 
2005         internal bool IsChangeInUserPrincipal {
2006             get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_USER_OBJECT) == FLAG_CHANGE_IN_USER_OBJECT; }
2007         }
2008 
2009         internal bool IsRuntimeErrorReported {
2010             get { return _runtimeErrorReported; }
2011         }
2012 
2013         internal bool IsSendResponseHeaders {
2014             get { return (_notificationContext.CurrentNotificationFlags & FLAG_SEND_RESPONSE_HEADERS) == FLAG_SEND_RESPONSE_HEADERS; }
2015         }
2016 
SetImpersonationEnabled()2017         internal void SetImpersonationEnabled() {
2018             IdentitySection c = RuntimeConfig.GetConfig(this).Identity;
2019             _impersonationEnabled = (c != null && c.Impersonate);
2020         }
2021 
2022         internal bool UsesImpersonation {
2023             get {
2024                 // if we're on a UNC share and we have a UNC token, then use impersonation for all notifications
2025                 if (HttpRuntime.IsOnUNCShareInternal && HostingEnvironment.ApplicationIdentityToken != IntPtr.Zero) {
2026                     return true;
2027                 }
2028                 // if <identity impersonate=/> is false, then don't use impersonation
2029                 if (!_impersonationEnabled) {
2030                     return false;
2031                 }
2032                 // the notification context won't be available after we have completed the transition
2033                 if (HasWebSocketRequestTransitionCompleted) {
2034                     return true;
2035                 }
2036 
2037                 // if this notification is after AuthenticateRequest and not a SendResponse notification, use impersonation
2038                 return (((_notificationContext.CurrentNotification == RequestNotification.AuthenticateRequest && _notificationContext.IsPostNotification)
2039                         || _notificationContext.CurrentNotification > RequestNotification.AuthenticateRequest)
2040                         && _notificationContext.CurrentNotification != RequestNotification.SendResponse);
2041             }
2042         }
2043 
2044         internal bool AreResponseHeadersSent {
2045             get { return (_notificationContext.CurrentNotificationFlags & FLAG_RESPONSE_HEADERS_SENT) == FLAG_RESPONSE_HEADERS_SENT; }
2046         }
2047 
NeedToInitializeApp()2048         internal bool NeedToInitializeApp() {
2049             bool needToInit = !_isAppInitialized;
2050             if (needToInit) {
2051                 _isAppInitialized = true;
2052             }
2053             return needToInit;
2054         }
2055 
2056         // flags passed in on the call to PipelineRuntime::ProcessRequestNotification
2057         internal int CurrentNotificationFlags {
2058             get {
2059                 return _notificationContext.CurrentNotificationFlags;
2060             }
2061             set {
2062                 _notificationContext.CurrentNotificationFlags = value;
2063             }
2064         }
2065 
2066         // index of the current "module" running the request
2067         // into the application module array
2068         internal int CurrentModuleIndex {
2069             get {
2070                 return _notificationContext.CurrentModuleIndex;
2071             }
2072             set {
2073                 _notificationContext.CurrentModuleIndex = value;
2074             }
2075         }
2076 
2077         // Each module has a PipelineModuleStepContainer
2078         // which stores/manages a list of event handlers
2079         // that correspond to each RequestNotification.
2080         // CurrentModuleEventIndex is the index (for the current
2081         // module) of the current event handler.
2082         // This will be greater than one when a single
2083         // module registers multiple delegates for a single event.
2084         // e.g.
2085         // app.BeginRequest += Foo;
2086         // app.BeginRequest += Bar;
2087         internal int CurrentModuleEventIndex {
2088             get {
2089                 return _notificationContext.CurrentModuleEventIndex;
2090             }
2091             set {
2092                 _notificationContext.CurrentModuleEventIndex = value;
2093             }
2094         }
2095 
DisableNotifications(RequestNotification notifications, RequestNotification postNotifications)2096         internal void DisableNotifications(RequestNotification notifications, RequestNotification postNotifications) {
2097             IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
2098             if (null != wr) {
2099                 wr.DisableNotifications(notifications, postNotifications);
2100             }
2101         }
2102 
2103         public bool IsPostNotification {
2104             get {
2105                 EnsureHasNotTransitionedToWebSocket();
2106 
2107                 if (!HttpRuntime.UseIntegratedPipeline) {
2108                     throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
2109                 }
2110                 return _notificationContext.IsPostNotification;
2111             }
2112             internal set {
2113                 if (!HttpRuntime.UseIntegratedPipeline) {
2114                     throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
2115                 }
2116                 _notificationContext.IsPostNotification = value;
2117             }
2118 
2119         }
2120 
2121         // user token for the request
2122         [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
2123         internal IntPtr ClientIdentityToken {
2124             get {
2125                 if (_wr != null) {
2126                     return _wr.GetUserToken();
2127                 }
2128                 else {
2129                     return IntPtr.Zero;
2130                 }
2131             }
2132         }
2133 
2134         // is configured to impersonate client?
2135         internal bool IsClientImpersonationConfigured {
2136             get {
2137                 try {
2138                     IdentitySection c = RuntimeConfig.GetConfig(this).Identity;
2139                     return (c != null && c.Impersonate && c.ImpersonateToken == IntPtr.Zero);
2140                 }
2141                 catch {
2142                     // this property should not throw as it is used in the error reporting pass
2143                     // config errors will be reported elsewhere
2144                     return false;
2145                 }
2146             }
2147         }
2148 
2149         internal IntPtr ImpersonationToken {
2150             get {
2151                 // by default use app identity
2152                 IntPtr token = HostingEnvironment.ApplicationIdentityToken;
2153                 IdentitySection c = RuntimeConfig.GetConfig(this).Identity;
2154                 if (c != null) {
2155                     if (c.Impersonate) {
2156                         token = (c.ImpersonateToken != IntPtr.Zero) ? c.ImpersonateToken : ClientIdentityToken;
2157                     }
2158                     else {
2159                         // for non-UNC case impersonate="false" means "don't impersonate",
2160                         // but there is a special case for UNC shares - even if
2161                         // impersonate="false" we still impersonate the UNC identity
2162                         // (hosting identity). and this is how v1.x works as well
2163                         if (!HttpRuntime.IsOnUNCShareInternal) {
2164                             token = IntPtr.Zero;
2165                         }
2166                     }
2167                 }
2168                 return token;
2169             }
2170         }
2171 
2172         internal AspNetSynchronizationContextBase SyncContext {
2173             get {
2174                 if (_syncContext == null) {
2175                     _syncContext = CreateNewAspNetSynchronizationContext();
2176                 }
2177 
2178                 return _syncContext;
2179             }
2180             set {
2181                 _syncContext = value;
2182             }
2183         }
2184 
InstallNewAspNetSynchronizationContext()2185         internal AspNetSynchronizationContextBase InstallNewAspNetSynchronizationContext() {
2186             AspNetSynchronizationContextBase syncContext = _syncContext;
2187 
2188             if (syncContext != null && syncContext == AsyncOperationManager.SynchronizationContext) {
2189                 // using current ASP.NET synchronization context - switch it
2190                 _syncContext = CreateNewAspNetSynchronizationContext();
2191                 AsyncOperationManager.SynchronizationContext = _syncContext;
2192                 return syncContext;
2193             }
2194 
2195             return null;
2196         }
2197 
CreateNewAspNetSynchronizationContext()2198         private AspNetSynchronizationContextBase CreateNewAspNetSynchronizationContext() {
2199             if (!AppSettings.UseTaskFriendlySynchronizationContext) {
2200                 return new LegacyAspNetSynchronizationContext(ApplicationInstance);
2201             }
2202             else {
2203                 return new AspNetSynchronizationContext(ApplicationInstance);
2204             }
2205         }
2206 
2207         [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
RestoreSavedAspNetSynchronizationContext(AspNetSynchronizationContextBase syncContext)2208         internal void RestoreSavedAspNetSynchronizationContext(AspNetSynchronizationContextBase syncContext) {
2209             AsyncOperationManager.SynchronizationContext = syncContext;
2210             _syncContext = syncContext;
2211         }
2212 
UserLanguagesFromContext()2213         internal string[] UserLanguagesFromContext() {
2214             return (Request != null) ? Request.UserLanguages : null;
2215         }
2216 
2217         // References should be nulled a.s.a.p. to reduce working set
ClearReferences()2218         internal void ClearReferences() {
2219             _appInstance = null;
2220             _handler = null;
2221             _handlerStack = null;
2222             _currentHandler = null;
2223             _remapHandler = null;
2224             if (_isIntegratedPipeline) {
2225                 if (!HasWebSocketRequestTransitionStarted) {
2226                     // Items is also used by AspNetWebSocketContext and should only be cleared if we're not transitioning to WebSockets
2227                     _items = null;
2228                 }
2229                 _syncContext = null;
2230             }
2231         }
2232 
CompleteTransitionToWebSocket()2233         internal void CompleteTransitionToWebSocket() {
2234             ClearReferencesForWebSocketProcessing();
2235 
2236             // transition: TransitionStarted -> TransitionCompleted
2237             TransitionToWebSocketState(WebSocketTransitionState.TransitionCompleted);
2238         }
2239 
2240         // This is much stronger than just ClearReferences; it tries to free absolutely as much memory as possible.
2241         // Some necessary items (like _wr, etc.) are preserved. The reason we want to modify this particular instance
2242         // in-place rather than create a new instance is that it is likely that references to this object still exist,
2243         // and we don't want the existence of those references to cause memory leaks.
ClearReferencesForWebSocketProcessing()2244         private void ClearReferencesForWebSocketProcessing() {
2245             HttpResponse response = _response;
2246 
2247             // everything not marked [DoNotReset] should be eligible for garbage collection
2248             ReflectionUtil.Reset(this);
2249 
2250             // Miscellaneous steps:
2251             _request.ClearReferencesForWebSocketProcessing(); // also clean up the HttpRequest instance
2252             if (response != null) {
2253                 // HttpResponse is off-limits, but it is possible that the developer accidentally maintained a reference
2254                 // to it, e.g. via a closure. We'll release the HttpResponse's references to all its data to prevent
2255                 // this from causing memory problems.
2256                 ReflectionUtil.Reset(response);
2257             }
2258         }
2259 
CultureFromConfig(string configString, bool requireSpecific)2260         internal CultureInfo CultureFromConfig(string configString, bool requireSpecific) {
2261             //auto
2262             if(StringUtil.EqualsIgnoreCase(configString, HttpApplication.AutoCulture)) {
2263                 string[] userLanguages = UserLanguagesFromContext();
2264                 if (userLanguages != null) {
2265                     try {
2266                         return CultureUtil.CreateReadOnlyCulture(userLanguages, requireSpecific);
2267                     }
2268                     catch {
2269                         return null;
2270                     }
2271                 }
2272                 else {
2273                     return null;
2274                 }
2275             }
2276             else if(StringUtil.StringStartsWithIgnoreCase(configString, "auto:")) {
2277                 string[] userLanguages = UserLanguagesFromContext();
2278                 if (userLanguages != null) {
2279                     try {
2280                         return CultureUtil.CreateReadOnlyCulture(userLanguages, requireSpecific);
2281                     }
2282                     catch {
2283                         return CultureUtil.CreateReadOnlyCulture(configString.Substring(5 /* "auto:".Length */), requireSpecific);
2284                     }
2285                 }
2286                 else {
2287                     return CultureUtil.CreateReadOnlyCulture(configString.Substring(5 /* "auto:".Length */), requireSpecific);
2288                 }
2289             }
2290 
2291             return CultureUtil.CreateReadOnlyCulture(configString, requireSpecific);
2292         }
2293 
2294         private enum WebSocketInitStatus {
2295             Success, // iiswsock.dll is active and has told us that the current request is a WebSocket request
2296             RequiresIntegratedMode, // WebSockets requires integrated mode, and the current server is not Integrated mode
2297             CannotCallFromBeginRequest, // We need to wait for BeginRequest to complete before the module has set the server variables
2298             NativeModuleNotEnabled, // iiswsock.dll isn't active in the pipeline
2299             NotAWebSocketRequest, // iiswsock.dll is active, but the current request is not a WebSocket request
2300             CurrentRequestIsChildRequest, // We are currently inside of a child request (IHttpContext::ExecuteRequest)
2301         }
2302 
AbortConnection()2303         private void AbortConnection() {
2304             IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
2305 
2306             if (wr != null) {
2307                 // Direct API Abort is suported in integrated mode only
2308                 wr.AbortConnection();
2309             }
2310             else {
2311                 // Close in classic mode acts as Abort (see HSE_REQ_CLOSE_CONNECTION)
2312                 // It closes the underlined connection
2313                 _wr.CloseConnection();
2314             }
2315         }
2316     }
2317 
2318     //
2319     // Helper class to add/remove HttpContext to/from CallContext
2320     //
2321     // using (new DisposableHttpContextWrapper(context)) {
2322     //     // this code will have HttpContext.Current working
2323     // }
2324     //
2325 
2326     internal class DisposableHttpContextWrapper : IDisposable {
2327         private bool _needToUndo;
2328         private HttpContext _savedContext;
2329 
SwitchContext(HttpContext context)2330         internal static HttpContext SwitchContext(HttpContext context) {
2331             return ContextBase.SwitchContext(context) as HttpContext;
2332         }
2333 
DisposableHttpContextWrapper(HttpContext context)2334         internal DisposableHttpContextWrapper(HttpContext context) {
2335             if (context != null) {
2336                 _savedContext = SwitchContext(context);
2337                 _needToUndo = (_savedContext != context);
2338             }
2339         }
2340 
IDisposable.Dispose()2341         void IDisposable.Dispose() {
2342             if (_needToUndo) {
2343                 SwitchContext(_savedContext);
2344                 _savedContext = null;
2345                 _needToUndo = false;
2346             }
2347         }
2348     }
2349 }
2350