1 //
2 // System.Web.HttpApplication.cs
3 //
4 // Author:
5 //	Miguel de Icaza (miguel@novell.com)
6 //	Gonzalo Paniagua (gonzalo@ximian.com)
7 //	Matthias Bogad (bogad@cs.tum.edu)
8 //
9 //
10 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 // The Application Processing Pipeline.
32 //
33 //     The Http application pipeline implemented in this file is a
34 //     beautiful thing.  The application pipeline invokes a number of
35 //     hooks at various stages of the processing of a request.  These
36 //     hooks can be either synchronous or can be asynchronous.
37 //
38 //     The pipeline must ensure that every step is completed before
39 //     moving to the next step.  A trivial thing for synchronous
40 //     hooks, but asynchronous hooks introduce an extra layer of
41 //     complexity: when the hook is invoked, the thread must
42 //     relinquish its control so that the thread can be reused in
43 //     another operation while waiting.
44 //
45 //     To implement this functionality we used C# iterators manually;
46 //     we drive the pipeline by executing the various hooks from the
47 //     `RunHooks' routine which is an enumerator that will yield the
48 //     value `false' if execution must proceed or `true' if execution
49 //     must be stopped.
50 //
51 //     By yielding values we can suspend execution of RunHooks.
52 //
53 //     Special attention must be given to `in_begin' and `must_yield'
54 //     variables.  These are used in the case that an async hook
55 //     completes synchronously as its important to not yield in that
56 //     case or we would hang.
57 //
58 //     Many of Mono modules used to be declared async, but they would
59 //     actually be completely synchronous, this might resurface in the
60 //     future with other modules.
61 //
62 // TODO:
63 //    Events Disposed
64 //
65 
66 using System;
67 using System.IO;
68 using System.Collections;
69 using System.Collections.Generic;
70 using System.ComponentModel;
71 using System.Configuration;
72 using System.Diagnostics;
73 using System.Globalization;
74 using System.Reflection;
75 using System.Security.Permissions;
76 using System.Security.Principal;
77 using System.Threading;
78 using System.Web.Caching;
79 using System.Web.Compilation;
80 using System.Web.Configuration;
81 using System.Web.Management;
82 using System.Web.SessionState;
83 using System.Web.UI;
84 using System.Web.Util;
85 
86 
87 namespace System.Web
88 {
89 	// CAS
90 	[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
91 	[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
92 	// attributes
93 	[ToolboxItem(false)]
94 	public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
95 	{
96 		static readonly object disposedEvent = new object ();
97 		static readonly object errorEvent = new object ();
98 
99 		// we do this static rather than per HttpApplication because
100 		// mono's perfcounters use the counter instance parameter for
101 		// the process to access shared memory.
102 		internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
103 
104 		internal static readonly string [] BinDirs = {"Bin", "bin"};
105 		object this_lock = new object();
106 
107 		HttpContext context;
108 		HttpSessionState session;
109 		ISite isite;
110 
111 		// The source, and the exposed API (cache).
112 		volatile HttpModuleCollection modcoll;
113 
114 		string assemblyLocation;
115 
116 		//
117 		// The factory for the handler currently running.
118 		//
119 		IHttpHandlerFactory factory;
120 
121 		//
122 		// Whether the thread culture is to be auto-set.
123 		// Used only in the 2.0 profile, always false for 1.x
124 		//
125 		bool autoCulture;
126 		bool autoUICulture;
127 
128 		//
129 		// Whether the pipeline should be stopped
130 		//
131 		bool stop_processing;
132 
133 		//
134 		// See https://bugzilla.novell.com/show_bug.cgi?id=381971
135 		//
136 		bool in_application_start;
137 
138 		//
139 		// The Pipeline
140 		//
141 		IEnumerator pipeline;
142 
143 		// To flag when we are done processing a request from BeginProcessRequest.
144 		ManualResetEvent done;
145 
146 		// The current IAsyncResult for the running async request handler in the pipeline
147 		AsyncRequestState begin_iar;
148 
149 		// Tracks the current AsyncInvocation being dispatched
150 		AsyncInvoker current_ai;
151 
152 		EventHandlerList events;
153 		EventHandlerList nonApplicationEvents = new EventHandlerList ();
154 
155 		// Culture and IPrincipal
156 		CultureInfo app_culture;
157 		CultureInfo appui_culture;
158 		CultureInfo prev_app_culture;
159 		CultureInfo prev_appui_culture;
160 		IPrincipal prev_user;
161 
162 		static string binDirectory;
163 
164 		static volatile Exception initialization_exception;
165 		bool removeConfigurationFromCache;
166 		bool fullInitComplete = false;
167 
168 		static DynamicModuleManager dynamicModuleManeger = new DynamicModuleManager ();
169 
170 		//
171 		// These are used to detect the case where the EndXXX method is invoked
172 		// from within the BeginXXXX delegate, so we detect whether we kick the
173 		// pipeline from here, or from the the RunHook routine
174 		//
175 		bool must_yield;
176 		bool in_begin;
177 
178 		public virtual event EventHandler Disposed {
179 			add { nonApplicationEvents.AddHandler (disposedEvent, value); }
180 			remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
181 		}
182 
183 		public virtual event EventHandler Error {
184 			add { nonApplicationEvents.AddHandler (errorEvent, value); }
185 			remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
186 		}
187 
HttpApplication()188 		public HttpApplication ()
189 		{
190 			done = new ManualResetEvent (false);
191 		}
192 
InitOnce(bool full_init)193 		internal void InitOnce (bool full_init)
194 		{
195 			if (initialization_exception != null)
196 				return;
197 
198 			if (modcoll != null)
199 				return;
200 
201 			lock (this_lock) {
202 				if (initialization_exception != null)
203 					return;
204 
205 				if (modcoll != null)
206 					return;
207 
208 				bool mustNullContext = context == null;
209 				try {
210 					HttpModulesSection modules;
211 					modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
212 					HttpContext saved = HttpContext.Current;
213 					HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest (String.Empty, String.Empty, new StringWriter()));
214 					if (context == null)
215 						context = HttpContext.Current;
216 					HttpModuleCollection coll = modules.LoadModules (this);
217 
218 					HttpModuleCollection dynMods = CreateDynamicModules ();
219 
220 					for (int i = 0; i < dynMods.Count; i++) {
221 						coll.AddModule (dynMods.GetKey (i), dynMods.Get (i));
222 					}
223 
224 					Interlocked.CompareExchange (ref modcoll, coll, null);
225 					HttpContext.Current = saved;
226 
227 					if (full_init) {
228 						HttpApplicationFactory.AttachEvents (this);
229 						Init ();
230 						fullInitComplete = true;
231 					}
232 				} catch (Exception e) {
233 					initialization_exception = e;
234 					Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
235 					// Once initialization_exception != null, we always respond with this exception
236 					// You have to restart the HttpApplication to "unlock" it
237 					Console.Error.WriteLine("Please restart your app to unlock it");
238 				} finally {
239 					if (mustNullContext)
240 						context = null;
241 				}
242 			}
243 		}
244 
245 		internal bool InApplicationStart {
246 			get { return in_application_start; }
247 			set { in_application_start = value; }
248 		}
249 
250 		internal string AssemblyLocation {
251 			get {
252 				if (assemblyLocation == null)
253 					assemblyLocation = GetType ().Assembly.Location;
254 				return assemblyLocation;
255 			}
256 		}
257 
258 		internal static Exception InitializationException {
259 			get { return initialization_exception; }
260 		}
261 
262 		[Browsable (false)]
263 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
264 		public HttpApplicationState Application {
265 			get {
266 				return HttpApplicationFactory.ApplicationState;
267 			}
268 		}
269 
270 		[Browsable (false)]
271 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
272 		public HttpContext Context {
273 			get {
274 				return context;
275 			}
276 		}
277 
278 		protected EventHandlerList Events {
279 			get {
280 				if (events == null)
281 					events = new EventHandlerList ();
282 
283 				return events;
284 			}
285 		}
286 
287 		[Browsable (false)]
288 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
289 		public HttpModuleCollection Modules {
290 			[AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
291 			get {
292 				if (modcoll == null)
293 					modcoll = new HttpModuleCollection ();
294 
295 				return modcoll;
296 			}
297 		}
298 
299 		[Browsable (false)]
300 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 		public HttpRequest Request {
302 			get {
303 				if (context == null)
304 					throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
305 
306 				if (false == HttpApplicationFactory.ContextAvailable)
307 					throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
308 
309 				return context.Request;
310 			}
311 		}
312 
313 		[Browsable (false)]
314 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
315 		public HttpResponse Response {
316 			get {
317 				if (context == null)
318 					throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
319 
320 				if (false == HttpApplicationFactory.ContextAvailable)
321 					throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
322 
323 				return context.Response;
324 			}
325 		}
326 
327 		[Browsable (false)]
328 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
329 		public HttpServerUtility Server {
330 			get {
331 				if (context != null)
332 					return context.Server;
333 
334 				//
335 				// This is so we can get the Server and call a few methods
336 				// which are not context sensitive, see HttpServerUtilityTest
337 				//
338 				return new HttpServerUtility ((HttpContext) null);
339 			}
340 		}
341 
342 		[Browsable (false)]
343 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
344 		public HttpSessionState Session {
345 			get {
346 				// Only used for Session_End
347 				if (session != null)
348 					return session;
349 
350 				if (context == null)
351 					throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
352 
353 				HttpSessionState ret = context.Session;
354 				if (ret == null)
355 					throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
356 
357 				return ret;
358 			}
359 		}
360 
361 		[Browsable (false)]
362 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
363 		public ISite Site {
364 			get { return isite; }
365 
366 			set { isite = value; }
367 		}
368 
369 		[Browsable (false)]
370 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
371 		public IPrincipal User {
372 			get {
373 				if (context == null)
374 					throw new HttpException (Locale.GetText ("No context is available."));
375 				if (context.User == null)
376 					throw new HttpException (Locale.GetText ("No currently authenticated user."));
377 
378 				return context.User;
379 			}
380 		}
381 
382 		static object PreSendRequestHeadersEvent = new object ();
383 		public event EventHandler PreSendRequestHeaders
384 		{
385 			add { AddEventHandler (PreSendRequestHeadersEvent, value); }
386 			remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
387 		}
388 
TriggerPreSendRequestHeaders()389 		internal void TriggerPreSendRequestHeaders ()
390 		{
391 			EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
392 			if (handler != null)
393 				handler (this, EventArgs.Empty);
394 		}
395 
396 		static object PreSendRequestContentEvent = new object ();
397 		public event EventHandler PreSendRequestContent
398 		{
399 			add { AddEventHandler (PreSendRequestContentEvent, value); }
400 			remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
401 		}
402 
TriggerPreSendRequestContent()403 		internal void TriggerPreSendRequestContent ()
404 		{
405 			EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
406 			if (handler != null)
407 				handler (this, EventArgs.Empty);
408 		}
409 
410 		static object AcquireRequestStateEvent = new object ();
411 		public event EventHandler AcquireRequestState
412 		{
413 			add { AddEventHandler (AcquireRequestStateEvent, value); }
414 			remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
415 		}
416 
AddOnAcquireRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)417 		public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
418 		{
419 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
420 			AcquireRequestState += new EventHandler (invoker.Invoke);
421 		}
422 
423 		static object AuthenticateRequestEvent = new object ();
424 		public event EventHandler AuthenticateRequest
425 		{
426 			add { AddEventHandler (AuthenticateRequestEvent, value); }
427 			remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
428 		}
429 
AddOnAuthenticateRequestAsync(BeginEventHandler bh, EndEventHandler eh)430 		public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
431 		{
432 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
433 			AuthenticateRequest += new EventHandler (invoker.Invoke);
434 		}
435 
436 		static object AuthorizeRequestEvent = new object ();
437 		public event EventHandler AuthorizeRequest
438 		{
439 			add { AddEventHandler (AuthorizeRequestEvent, value); }
440 			remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
441 		}
442 
AddOnAuthorizeRequestAsync(BeginEventHandler bh, EndEventHandler eh)443 		public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
444 		{
445 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
446 			AuthorizeRequest += new EventHandler (invoker.Invoke);
447 		}
448 
449 		static object BeginRequestEvent = new object ();
450 		public event EventHandler BeginRequest
451 		{
452 			add {
453 				// See https://bugzilla.novell.com/show_bug.cgi?id=381971
454 				if (InApplicationStart)
455 					return;
456 				AddEventHandler (BeginRequestEvent, value);
457 			}
458 			remove {
459 				if (InApplicationStart)
460 					return;
461 				RemoveEventHandler (BeginRequestEvent, value);
462 			}
463 		}
464 
AddOnBeginRequestAsync(BeginEventHandler bh, EndEventHandler eh)465 		public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
466 		{
467 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
468 			BeginRequest += new EventHandler (invoker.Invoke);
469 		}
470 
471 		static object EndRequestEvent = new object ();
472 		public event EventHandler EndRequest
473 		{
474 			add {
475 				// See https://bugzilla.novell.com/show_bug.cgi?id=381971
476 				if (InApplicationStart)
477 					return;
478 				AddEventHandler (EndRequestEvent, value);
479 			}
480 			remove {
481 				if (InApplicationStart)
482 					return;
483 				RemoveEventHandler (EndRequestEvent, value);
484 			}
485 		}
486 
AddOnEndRequestAsync(BeginEventHandler bh, EndEventHandler eh)487 		public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
488 		{
489 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
490 			EndRequest += new EventHandler (invoker.Invoke);
491 		}
492 
493 		static object PostRequestHandlerExecuteEvent = new object ();
494 		public event EventHandler PostRequestHandlerExecute
495 		{
496 			add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
497 			remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
498 		}
499 
AddOnPostRequestHandlerExecuteAsync(BeginEventHandler bh, EndEventHandler eh)500 		public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
501 		{
502 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
503 			PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
504 		}
505 
506 		static object PreRequestHandlerExecuteEvent = new object ();
507 		public event EventHandler PreRequestHandlerExecute
508 		{
509 			add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
510 			remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
511 		}
512 
AddOnPreRequestHandlerExecuteAsync(BeginEventHandler bh, EndEventHandler eh)513 		public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
514 		{
515 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
516 			PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
517 		}
518 
519 		static object ReleaseRequestStateEvent = new object ();
520 		public event EventHandler ReleaseRequestState
521 		{
522 			add { AddEventHandler (ReleaseRequestStateEvent, value); }
523 			remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
524 		}
525 
AddOnReleaseRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)526 		public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
527 		{
528 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
529 			ReleaseRequestState += new EventHandler (invoker.Invoke);
530 		}
531 
532 		static object ResolveRequestCacheEvent = new object ();
533 		public event EventHandler ResolveRequestCache
534 		{
535 			add { AddEventHandler (ResolveRequestCacheEvent, value); }
536 			remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
537 		}
538 
AddOnResolveRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)539 		public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
540 		{
541 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
542 			ResolveRequestCache += new EventHandler (invoker.Invoke);
543 		}
544 
545 		static object UpdateRequestCacheEvent = new object ();
546 		public event EventHandler UpdateRequestCache
547 		{
548 			add { AddEventHandler (UpdateRequestCacheEvent, value); }
549 			remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
550 		}
551 
AddOnUpdateRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)552 		public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
553 		{
554 			AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
555 			UpdateRequestCache += new EventHandler (invoker.Invoke);
556 		}
557 
558 		static object PostAuthenticateRequestEvent = new object ();
559 		public event EventHandler PostAuthenticateRequest
560 		{
561 			add { AddEventHandler (PostAuthenticateRequestEvent, value); }
562 			remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
563 		}
564 
AddOnPostAuthenticateRequestAsync(BeginEventHandler bh, EndEventHandler eh)565 		public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
566 		{
567 			AddOnPostAuthenticateRequestAsync (bh, eh, null);
568 		}
569 
AddOnPostAuthenticateRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)570 		public void AddOnPostAuthenticateRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
571 		{
572 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
573 			PostAuthenticateRequest += new EventHandler (invoker.Invoke);
574 		}
575 
576 		static object PostAuthorizeRequestEvent = new object ();
577 		public event EventHandler PostAuthorizeRequest
578 		{
579 			add { AddEventHandler (PostAuthorizeRequestEvent, value); }
580 			remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
581 		}
582 
AddOnPostAuthorizeRequestAsync(BeginEventHandler bh, EndEventHandler eh)583 		public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
584 		{
585 			AddOnPostAuthorizeRequestAsync (bh, eh, null);
586 		}
587 
AddOnPostAuthorizeRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)588 		public void AddOnPostAuthorizeRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
589 		{
590 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
591 			PostAuthorizeRequest += new EventHandler (invoker.Invoke);
592 		}
593 
594 		static object PostResolveRequestCacheEvent = new object ();
595 		public event EventHandler PostResolveRequestCache
596 		{
597 			add { AddEventHandler (PostResolveRequestCacheEvent, value); }
598 			remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
599 		}
600 
AddOnPostResolveRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)601 		public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
602 		{
603 			AddOnPostResolveRequestCacheAsync (bh, eh, null);
604 		}
605 
AddOnPostResolveRequestCacheAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)606 		public void AddOnPostResolveRequestCacheAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
607 		{
608 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
609 			PostResolveRequestCache += new EventHandler (invoker.Invoke);
610 		}
611 
612 		static object PostMapRequestHandlerEvent = new object ();
613 		public event EventHandler PostMapRequestHandler
614 		{
615 			add { AddEventHandler (PostMapRequestHandlerEvent, value); }
616 			remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
617 		}
618 
AddOnPostMapRequestHandlerAsync(BeginEventHandler bh, EndEventHandler eh)619 		public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
620 		{
621 			AddOnPostMapRequestHandlerAsync (bh, eh, null);
622 		}
623 
AddOnPostMapRequestHandlerAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)624 		public void AddOnPostMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
625 		{
626 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
627 			PostMapRequestHandler += new EventHandler (invoker.Invoke);
628 		}
629 
630 		static object PostAcquireRequestStateEvent = new object ();
631 		public event EventHandler PostAcquireRequestState
632 		{
633 			add { AddEventHandler (PostAcquireRequestStateEvent, value); }
634 			remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
635 		}
636 
AddOnPostAcquireRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)637 		public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
638 		{
639 			AddOnPostAcquireRequestStateAsync (bh, eh, null);
640 		}
641 
AddOnPostAcquireRequestStateAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)642 		public void AddOnPostAcquireRequestStateAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
643 		{
644 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
645 			PostAcquireRequestState += new EventHandler (invoker.Invoke);
646 		}
647 
648 		static object PostReleaseRequestStateEvent = new object ();
649 		public event EventHandler PostReleaseRequestState
650 		{
651 			add { AddEventHandler (PostReleaseRequestStateEvent, value); }
652 			remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
653 		}
654 
AddOnPostReleaseRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)655 		public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
656 		{
657 			AddOnPostReleaseRequestStateAsync (bh, eh, null);
658 		}
659 
AddOnPostReleaseRequestStateAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)660 		public void AddOnPostReleaseRequestStateAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
661 		{
662 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
663 			PostReleaseRequestState += new EventHandler (invoker.Invoke);
664 		}
665 
666 		static object PostUpdateRequestCacheEvent = new object ();
667 		public event EventHandler PostUpdateRequestCache
668 		{
669 			add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
670 			remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
671 		}
672 
AddOnPostUpdateRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)673 		public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
674 		{
675 			AddOnPostUpdateRequestCacheAsync (bh, eh, null);
676 		}
677 
AddOnPostUpdateRequestCacheAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)678 		public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
679 		{
680 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
681 			PostUpdateRequestCache += new EventHandler (invoker.Invoke);
682 		}
683 
684 		//
685 		// The new overloads that take a data parameter
686 		//
AddOnAcquireRequestStateAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)687 		public void AddOnAcquireRequestStateAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
688 		{
689 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
690 			AcquireRequestState += new EventHandler (invoker.Invoke);
691 		}
692 
AddOnAuthenticateRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)693 		public void AddOnAuthenticateRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
694 		{
695 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
696 			AuthenticateRequest += new EventHandler (invoker.Invoke);
697 		}
698 
AddOnAuthorizeRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)699 		public void AddOnAuthorizeRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
700 		{
701 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
702 			AuthorizeRequest += new EventHandler (invoker.Invoke);
703 		}
704 
AddOnBeginRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)705 		public void AddOnBeginRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
706 		{
707 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
708 			BeginRequest += new EventHandler (invoker.Invoke);
709 		}
710 
AddOnEndRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)711 		public void AddOnEndRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
712 		{
713 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
714 			EndRequest += new EventHandler (invoker.Invoke);
715 		}
716 
AddOnPostRequestHandlerExecuteAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)717 			public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
718 		{
719 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
720 			PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
721 		}
722 
AddOnPreRequestHandlerExecuteAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)723 			public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
724 		{
725 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
726 			PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
727 		}
728 
AddOnReleaseRequestStateAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)729 		public void AddOnReleaseRequestStateAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
730 		{
731 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
732 			ReleaseRequestState += new EventHandler (invoker.Invoke);
733 		}
734 
AddOnResolveRequestCacheAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)735 		public void AddOnResolveRequestCacheAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
736 		{
737 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
738 			ResolveRequestCache += new EventHandler (invoker.Invoke);
739 		}
740 
AddOnUpdateRequestCacheAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)741 		public void AddOnUpdateRequestCacheAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
742 		{
743 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
744 			UpdateRequestCache += new EventHandler (invoker.Invoke);
745 		}
746 
747 		// Added in 2.0 SP1
748 		// They are for use with the IIS7 integrated mode, but have been added for
749 		// compatibility
750 		static object LogRequestEvent = new object ();
751 		public event EventHandler LogRequest
752 		{
753 			add { AddEventHandler (LogRequestEvent, value); }
754 			remove { RemoveEventHandler (LogRequestEvent, value); }
755 		}
756 
AddOnLogRequestAsync(BeginEventHandler bh, EndEventHandler eh)757 		public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
758 		{
759 			AddOnLogRequestAsync (bh, eh, null);
760 		}
761 
AddOnLogRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)762 		public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
763 		{
764 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
765 			LogRequest += new EventHandler (invoker.Invoke);
766 		}
767 
768 		static object MapRequestHandlerEvent = new object ();
769 		public event EventHandler MapRequestHandler
770 		{
771 			add { AddEventHandler (MapRequestHandlerEvent, value); }
772 			remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
773 		}
774 
AddOnMapRequestHandlerAsync(BeginEventHandler bh, EndEventHandler eh)775 		public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
776 		{
777 			AddOnMapRequestHandlerAsync (bh, eh, null);
778 		}
779 
AddOnMapRequestHandlerAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)780 		public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
781 		{
782 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
783 			MapRequestHandler += new EventHandler (invoker.Invoke);
784 		}
785 
786 		static object PostLogRequestEvent = new object ();
787 		public event EventHandler PostLogRequest
788 		{
789 			add { AddEventHandler (PostLogRequestEvent, value); }
790 			remove { RemoveEventHandler (PostLogRequestEvent, value); }
791 		}
792 
AddOnPostLogRequestAsync(BeginEventHandler bh, EndEventHandler eh)793 		public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
794 		{
795 			AddOnPostLogRequestAsync (bh, eh, null);
796 		}
797 
AddOnPostLogRequestAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, object state)798 		public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
799 		{
800 			AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
801 			PostLogRequest += new EventHandler (invoker.Invoke);
802 		}
803 
804 		internal event EventHandler DefaultAuthentication;
805 
AddEventHandler(object key, EventHandler handler)806 		void AddEventHandler (object key, EventHandler handler)
807 		{
808 			if (fullInitComplete)
809 				return;
810 
811 			Events.AddHandler (key, handler);
812 		}
813 
RemoveEventHandler(object key, EventHandler handler)814 		void RemoveEventHandler (object key, EventHandler handler)
815 		{
816 			if (fullInitComplete)
817 				return;
818 
819 			Events.RemoveHandler (key, handler);
820 		}
821 
822 		//
823 		// Bypass all the event on the Http pipeline and go directly to EndRequest
824 		//
CompleteRequest()825 		public void CompleteRequest ()
826 		{
827 			stop_processing = true;
828 		}
829 
830 		internal bool RequestCompleted {
831 			set { stop_processing = value; }
832 		}
833 
DisposeInternal()834 		internal void DisposeInternal ()
835 		{
836 			Dispose ();
837 			HttpModuleCollection coll = new HttpModuleCollection ();
838 			Interlocked.Exchange (ref modcoll, coll);
839 			if (coll != null) {
840 				for (int i = coll.Count - 1; i >= 0; i--) {
841 					coll.Get (i).Dispose ();
842 				}
843 				coll = null;
844 			}
845 
846 			EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
847 			if (eh != null)
848 				eh (this, EventArgs.Empty);
849 
850 			done.Close ();
851 			done = null;
852 		}
853 
Dispose()854 		public virtual void Dispose ()
855 		{
856 		}
857 
GetOutputCacheProviderName(HttpContext context)858 		public virtual string GetOutputCacheProviderName (HttpContext context)
859 		{
860 			// LAMESPEC: doesn't throw ProviderException if context is null
861 			return OutputCache.DefaultProviderName;
862 		}
863 
GetVaryByCustomString(HttpContext context, string custom)864 		public virtual string GetVaryByCustomString (HttpContext context, string custom)
865 		{
866 			if (custom == null) // Sigh
867 				throw new NullReferenceException ();
868 
869 			if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
870 				return context.Request.Browser.Type;
871 
872 			return null;
873 		}
874 
ShouldHandleException(Exception e)875 		bool ShouldHandleException (Exception e)
876 		{
877 			if (e is ParseException)
878 				return false;
879 
880 			return true;
881 		}
882 
883 		//
884 		// If we catch an error, queue this error
885 		//
ProcessError(Exception e)886 		internal void ProcessError (Exception e)
887 		{
888 			bool first = context.Error == null;
889 			context.AddError (e);
890 			if (first && ShouldHandleException (e)) {
891 				EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
892 				if (eh != null){
893 					try {
894 						eh (this, EventArgs.Empty);
895 						if (stop_processing)
896 							context.ClearError ();
897 					} catch (ThreadAbortException taex){
898 						context.ClearError ();
899 						if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
900 							// This happens on Redirect(), End() and
901 							// when unloading the AppDomain
902 							Thread.ResetAbort ();
903 						else
904 							// This happens on Thread.Abort()
905 							context.AddError (taex);
906 					} catch (Exception ee){
907 						context.AddError (ee);
908 					}
909 				}
910 			}
911 			stop_processing = true;
912 
913 			// we want to remove configuration from the cache in case of
914 			// invalid resource not exists to prevent DOS attack.
915 			HttpException httpEx = e as HttpException;
916 			if (httpEx != null && httpEx.GetHttpCode () == 404) {
917 				removeConfigurationFromCache = true;
918 			}
919 		}
920 
921 		//
922 		// Ticks the clock: next step on the pipeline.
923 		//
Tick()924 		internal void Tick ()
925 		{
926 			try {
927 				if (pipeline.MoveNext ()){
928 					if ((bool)pipeline.Current)
929 						PipelineDone ();
930 				}
931 			} catch (ThreadAbortException taex) {
932 				object obj = taex.ExceptionState;
933 				Thread.ResetAbort ();
934 				if (obj is StepTimeout)
935 					ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
936 				else {
937 					context.ClearError ();
938 					if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
939 						context.AddError (taex);
940 				}
941 
942 				stop_processing = true;
943 				PipelineDone ();
944 			} catch (Exception e) {
945 				ThreadAbortException inner = e.InnerException as ThreadAbortException;
946 				if (inner != null && FlagEnd.Value == inner.ExceptionState && !HttpRuntime.DomainUnloading) {
947 					context.ClearError ();
948 					Thread.ResetAbort ();
949 				} else {
950 					ProcessError (e);
951 				}
952 				stop_processing = true;
953 				PipelineDone ();
954 			}
955 		}
956 
Resume()957 		void Resume ()
958 		{
959 			if (in_begin)
960 				must_yield = false;
961 			else
962 				Tick ();
963 		}
964 
965 		//
966 		// Invoked when our async callback called from RunHooks completes,
967 		// we restart the pipeline here.
968 		//
async_callback_completed_cb(IAsyncResult ar)969 		void async_callback_completed_cb (IAsyncResult ar)
970 		{
971 			if (current_ai.end != null){
972 				try {
973 					current_ai.end (ar);
974 				} catch (Exception e) {
975 					ProcessError (e);
976 				}
977 			}
978 
979 			Resume ();
980 		}
981 
async_handler_complete_cb(IAsyncResult ar)982 		void async_handler_complete_cb (IAsyncResult ar)
983 		{
984 			IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
985 
986 			try {
987 				if (async_handler != null)
988 					async_handler.EndProcessRequest (ar);
989 			} catch (Exception e){
990 				ProcessError (e);
991 			}
992 
993 			Resume ();
994 		}
995 
996 		//
997 		// This enumerator yields whether processing must be stopped:
998 		//    true:  processing of the pipeline must be stopped
999 		//    false: processing of the pipeline must not be stopped
1000 		//
RunHooks(Delegate list)1001 		IEnumerable RunHooks (Delegate list)
1002 		{
1003 			Delegate [] delegates = list.GetInvocationList ();
1004 
1005 			foreach (EventHandler d in delegates){
1006 				if (d.Target != null && (d.Target is AsyncInvoker)){
1007 					current_ai = (AsyncInvoker) d.Target;
1008 
1009 					try {
1010 						must_yield = true;
1011 						in_begin = true;
1012 						context.BeginTimeoutPossible ();
1013 						current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1014 					} finally {
1015 						in_begin = false;
1016 						context.EndTimeoutPossible ();
1017 					}
1018 
1019 					//
1020 					// If things are still moving forward, yield this
1021 					// thread now
1022 					//
1023 					if (must_yield)
1024 						yield return stop_processing;
1025 					else if (stop_processing)
1026 						yield return true;
1027 				} else {
1028 					try {
1029 						context.BeginTimeoutPossible ();
1030 						d (this, EventArgs.Empty);
1031 					} finally {
1032 						context.EndTimeoutPossible ();
1033 					}
1034 					if (stop_processing)
1035 						yield return true;
1036 				}
1037 			}
1038 		}
1039 
FinalErrorWrite(HttpResponse response, string error)1040 		static void FinalErrorWrite (HttpResponse response, string error)
1041 		{
1042 			try {
1043 				response.Write (error);
1044 				response.Flush (true);
1045 			} catch {
1046 				response.Close ();
1047 			}
1048 		}
1049 
OutputPage()1050 		void OutputPage ()
1051 		{
1052 			if (context.Error == null){
1053 				try {
1054 					context.Response.Flush (true);
1055 				} catch (Exception e){
1056 					context.AddError (e);
1057 				}
1058 			}
1059 
1060 			Exception error = context.Error;
1061 			if (error != null){
1062 				HttpResponse response = context.Response;
1063 
1064 				if (!response.HeadersSent){
1065 					response.ClearHeaders ();
1066 					response.ClearContent ();
1067 
1068 					if (error is HttpException){
1069 						response.StatusCode = ((HttpException)error).GetHttpCode ();
1070 					} else {
1071 						error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1072 						response.StatusCode = 500;
1073 					}
1074 					HttpException httpEx = (HttpException) error;
1075 					if (!RedirectCustomError (ref httpEx))
1076 						FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1077 					else
1078 						response.Flush (true);
1079 				} else {
1080 					if (!(error is HttpException))
1081 						error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1082 					FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1083 				}
1084 			}
1085 
1086 		}
1087 
1088 		//
1089 		// Invoked at the end of the pipeline execution
1090 		//
PipelineDone()1091 		void PipelineDone ()
1092 		{
1093 			try {
1094 				EventHandler handler = Events [EndRequestEvent] as EventHandler;
1095 				if (handler != null)
1096 					handler (this, EventArgs.Empty);
1097 			} catch (Exception e){
1098 				ProcessError (e);
1099 			}
1100 
1101 			try {
1102 				OutputPage ();
1103 			} catch (ThreadAbortException taex) {
1104 				ProcessError (taex);
1105 				Thread.ResetAbort ();
1106 			} catch (Exception e) {
1107 				Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1108 			} finally {
1109 				context.WorkerRequest.EndOfRequest();
1110 				if (factory != null && context.Handler != null){
1111 					factory.ReleaseHandler (context.Handler);
1112 					context.Handler = null;
1113 					factory = null;
1114 				}
1115 				context.PopHandler ();
1116 
1117 				// context = null; -> moved to PostDone
1118 				pipeline = null;
1119 				current_ai = null;
1120 			}
1121 			PostDone ();
1122 
1123 			if (begin_iar != null)
1124 				begin_iar.Complete ();
1125 			else
1126 				done.Set ();
1127 
1128 			requests_total_counter.Increment ();
1129 		}
1130 
1131 		class Tim {
1132 			string name;
1133 			DateTime start;
1134 
Tim()1135 			public Tim () {
1136 			}
1137 
Tim(string name)1138 			public Tim (string name) {
1139 				this.name = name;
1140 			}
1141 
1142 			public string Name {
1143 				get { return name; }
1144 				set { name = value; }
1145 			}
1146 
Start()1147 			public void Start () {
1148 				start = DateTime.UtcNow;
1149 			}
1150 
Stop()1151 			public void Stop () {
1152 				Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1153 			}
1154 		}
1155 
1156 		Tim tim;
1157 		[Conditional ("PIPELINE_TIMER")]
StartTimer(string name)1158 		void StartTimer (string name)
1159 		{
1160 			if (tim == null)
1161 				tim = new Tim ();
1162 			tim.Name = name;
1163 			tim.Start ();
1164 		}
1165 
1166 		[Conditional ("PIPELINE_TIMER")]
StopTimer()1167 		void StopTimer ()
1168 		{
1169 			tim.Stop ();
1170 		}
1171 
1172 		//
1173 		// Events fired as described in `Http Runtime Support, HttpModules,
1174 		// Handling Public Events'
1175 		//
Pipeline()1176 		IEnumerator Pipeline ()
1177 		{
1178 			Delegate eventHandler;
1179 			if (stop_processing)
1180 				yield return true;
1181 			HttpRequest req = context.Request;
1182 			if (req != null)
1183 				req.Validate ();
1184 			context.MapRequestHandlerDone = false;
1185 			StartTimer ("BeginRequest");
1186 			eventHandler = Events [BeginRequestEvent];
1187 			if (eventHandler != null) {
1188 				foreach (bool stop in RunHooks (eventHandler))
1189 					yield return stop;
1190 			}
1191 			StopTimer ();
1192 
1193 			StartTimer ("AuthenticateRequest");
1194 			eventHandler = Events [AuthenticateRequestEvent];
1195 			if (eventHandler != null)
1196 				foreach (bool stop in RunHooks (eventHandler))
1197 					yield return stop;
1198 			StopTimer ();
1199 
1200 			StartTimer ("DefaultAuthentication");
1201 			if (DefaultAuthentication != null)
1202 				foreach (bool stop in RunHooks (DefaultAuthentication))
1203 					yield return stop;
1204 			StopTimer ();
1205 
1206 			StartTimer ("PostAuthenticateRequest");
1207 			eventHandler = Events [PostAuthenticateRequestEvent];
1208 			if (eventHandler != null)
1209 				foreach (bool stop in RunHooks (eventHandler))
1210 					yield return stop;
1211 			StopTimer ();
1212 
1213 			StartTimer ("AuthorizeRequest");
1214 			eventHandler = Events [AuthorizeRequestEvent];
1215 			if (eventHandler != null)
1216 				foreach (bool stop in RunHooks (eventHandler))
1217 					yield return stop;
1218 			StopTimer ();
1219 
1220 			StartTimer ("PostAuthorizeRequest");
1221 			eventHandler = Events [PostAuthorizeRequestEvent];
1222 			if (eventHandler != null)
1223 				foreach (bool stop in RunHooks (eventHandler))
1224 					yield return stop;
1225 			StopTimer ();
1226 
1227 			StartTimer ("ResolveRequestCache");
1228 			eventHandler = Events [ResolveRequestCacheEvent];
1229 			if (eventHandler != null)
1230 				foreach (bool stop in RunHooks (eventHandler))
1231 					yield return stop;
1232 			StopTimer ();
1233 
1234 			StartTimer ("PostResolveRequestCache");
1235 			eventHandler = Events [PostResolveRequestCacheEvent];
1236 			if (eventHandler != null)
1237 				foreach (bool stop in RunHooks (eventHandler))
1238 					yield return stop;
1239 			StopTimer ();
1240 
1241 			StartTimer ("MapRequestHandler");
1242 			// As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1243 			eventHandler = Events [MapRequestHandlerEvent];
1244 			if (eventHandler != null)
1245 				foreach (bool stop in RunHooks (eventHandler))
1246 					yield return stop;
1247 			StopTimer ();
1248 			context.MapRequestHandlerDone = true;
1249 
1250 			StartTimer ("GetHandler");
1251 			// Obtain the handler for the request.
1252 			IHttpHandler handler = null;
1253 			try {
1254 				handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1255 				context.Handler = handler;
1256 				context.PushHandler (handler);
1257 			} catch (FileNotFoundException fnf){
1258 				if (context.Request.IsLocal)
1259 					ProcessError (HttpException.NewWithCode (404,
1260 										 String.Format ("File not found {0}", fnf.FileName),
1261 										 fnf,
1262 										 context.Request.FilePath,
1263 										 WebEventCodes.RuntimeErrorRequestAbort));
1264 				else
1265 					ProcessError (HttpException.NewWithCode (404,
1266 										 "File not found: " + Path.GetFileName (fnf.FileName),
1267 										 context.Request.FilePath,
1268 										 WebEventCodes.RuntimeErrorRequestAbort));
1269 			} catch (DirectoryNotFoundException dnf){
1270 				if (!context.Request.IsLocal)
1271 					dnf = null; // Do not "leak" real path information
1272 				ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
1273 			} catch (Exception e) {
1274 				ProcessError (e);
1275 			}
1276 
1277 			StopTimer ();
1278 			if (stop_processing)
1279 				yield return true;
1280 
1281 			StartTimer ("PostMapRequestHandler");
1282 			eventHandler = Events [PostMapRequestHandlerEvent];
1283 			if (eventHandler != null)
1284 				foreach (bool stop in RunHooks (eventHandler))
1285 					yield return stop;
1286 			StopTimer ();
1287 
1288 			StartTimer ("AcquireRequestState");
1289 			eventHandler = Events [AcquireRequestStateEvent];
1290 			if (eventHandler != null){
1291 				foreach (bool stop in RunHooks (eventHandler))
1292 					yield return stop;
1293 			}
1294 			StopTimer ();
1295 
1296 			StartTimer ("PostAcquireRequestState");
1297 			eventHandler = Events [PostAcquireRequestStateEvent];
1298 			if (eventHandler != null){
1299 				foreach (bool stop in RunHooks (eventHandler))
1300 					yield return stop;
1301 			}
1302 			StopTimer ();
1303 
1304 			//
1305 			// From this point on, we need to ensure that we call
1306 			// ReleaseRequestState, so the code below jumps to
1307 			// `release:' to guarantee it rather than yielding.
1308 			//
1309 			StartTimer ("PreRequestHandlerExecute");
1310 			eventHandler = Events [PreRequestHandlerExecuteEvent];
1311 			if (eventHandler != null)
1312 				foreach (bool stop in RunHooks (eventHandler))
1313 					if (stop)
1314 						goto release;
1315 			StopTimer ();
1316 
1317 
1318 
1319 			IHttpHandler ctxHandler = context.Handler;
1320 			if (ctxHandler != null && handler != ctxHandler) {
1321 				context.PopHandler ();
1322 				handler = ctxHandler;
1323 				context.PushHandler (handler);
1324 			}
1325 
1326 			StartTimer ("ProcessRequest");
1327 			try {
1328 				context.BeginTimeoutPossible ();
1329 				if (handler != null){
1330 					IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1331 
1332 					if (async_handler != null){
1333 						must_yield = true;
1334 						in_begin = true;
1335 						async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1336 					} else {
1337 						must_yield = false;
1338 						handler.ProcessRequest (context);
1339 					}
1340 				} else
1341 					throw new InvalidOperationException ("No handler for the current request.");
1342 				if (context.Error != null)
1343 					throw new TargetInvocationException(context.Error);
1344 			} finally {
1345 				in_begin = false;
1346 				context.EndTimeoutPossible ();
1347 			}
1348 			StopTimer ();
1349 			if (must_yield)
1350 				yield return stop_processing;
1351 			else if (stop_processing)
1352 				goto release;
1353 
1354 			// These are executed after the application has returned
1355 
1356 			StartTimer ("PostRequestHandlerExecute");
1357 			eventHandler = Events [PostRequestHandlerExecuteEvent];
1358 			if (eventHandler != null)
1359 				foreach (bool stop in RunHooks (eventHandler))
1360 					if (stop)
1361 						goto release;
1362 			StopTimer ();
1363 
1364 		release:
1365 			StartTimer ("ReleaseRequestState");
1366 			eventHandler = Events [ReleaseRequestStateEvent];
1367 			if (eventHandler != null){
1368 #pragma warning disable 219
1369 				foreach (bool stop in RunHooks (eventHandler)) {
1370 					//
1371 					// Ignore the stop signal while release the state
1372 					//
1373 
1374 				}
1375 #pragma warning restore 219
1376 			}
1377 			StopTimer ();
1378 
1379 			if (stop_processing)
1380 				yield return true;
1381 
1382 			StartTimer ("PostReleaseRequestState");
1383 			eventHandler = Events [PostReleaseRequestStateEvent];
1384 			if (eventHandler != null)
1385 				foreach (bool stop in RunHooks (eventHandler))
1386 					yield return stop;
1387 			StopTimer ();
1388 
1389 			StartTimer ("Filter");
1390 			if (context.Error == null)
1391 				context.Response.DoFilter (true);
1392 			StopTimer ();
1393 
1394 			StartTimer ("UpdateRequestCache");
1395 			eventHandler = Events [UpdateRequestCacheEvent];
1396 			if (eventHandler != null)
1397 				foreach (bool stop in RunHooks (eventHandler))
1398 					yield return stop;
1399 			StopTimer ();
1400 
1401 			StartTimer ("PostUpdateRequestCache");
1402 			eventHandler = Events [PostUpdateRequestCacheEvent];
1403 			if (eventHandler != null)
1404 				foreach (bool stop in RunHooks (eventHandler))
1405 					yield return stop;
1406 			StopTimer ();
1407 
1408 			StartTimer ("LogRequest");
1409 			eventHandler = Events [LogRequestEvent];
1410 			if (eventHandler != null)
1411 				foreach (bool stop in RunHooks (eventHandler))
1412 					yield return stop;
1413 			StopTimer ();
1414 
1415 			StartTimer ("PostLogRequest");
1416 			eventHandler = Events [PostLogRequestEvent];
1417 			if (eventHandler != null)
1418 				foreach (bool stop in RunHooks (eventHandler))
1419 					yield return stop;
1420 			StopTimer ();
1421 
1422 			StartTimer ("PipelineDone");
1423 			PipelineDone ();
1424 			StopTimer ();
1425 		}
1426 
1427 
GetThreadCulture(HttpRequest request, CultureInfo culture, bool isAuto)1428 		internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1429 		{
1430 			if (!isAuto)
1431 				return culture;
1432 			CultureInfo ret = null;
1433 			string[] languages = request.UserLanguages;
1434 			try {
1435 				if (languages != null && languages.Length > 0)
1436 					ret = CultureInfo.CreateSpecificCulture (languages[0]);
1437 			} catch {
1438 			}
1439 
1440 			if (ret == null)
1441 				ret = culture;
1442 
1443 			return ret;
1444 		}
1445 
1446 
PreStart()1447 		void PreStart ()
1448 		{
1449 			GlobalizationSection cfg;
1450 			cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1451 			app_culture = cfg.GetCulture ();
1452 			autoCulture = cfg.IsAutoCulture;
1453 			appui_culture = cfg.GetUICulture ();
1454 			autoUICulture = cfg.IsAutoUICulture;
1455 			context.StartTimeoutTimer ();
1456 			Thread th = Thread.CurrentThread;
1457 			if (app_culture != null) {
1458 				prev_app_culture = th.CurrentCulture;
1459 				CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1460 				if (!new_app_culture.Equals (Helpers.InvariantCulture))
1461 					th.CurrentCulture = new_app_culture;
1462 			}
1463 
1464 			if (appui_culture != null) {
1465 				prev_appui_culture = th.CurrentUICulture;
1466 				CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1467 				if (!new_app_culture.Equals (Helpers.InvariantCulture))
1468 					th.CurrentUICulture = new_app_culture;
1469 			}
1470 
1471 			prev_user = Thread.CurrentPrincipal;
1472 		}
1473 
PostDone()1474 		void PostDone ()
1475 		{
1476 			if (removeConfigurationFromCache) {
1477 				WebConfigurationManager.RemoveConfigurationFromCache (context);
1478 				removeConfigurationFromCache = false;
1479 			}
1480 
1481 			Thread th = Thread.CurrentThread;
1482 			if (Thread.CurrentPrincipal != prev_user)
1483 				Thread.CurrentPrincipal = prev_user;
1484 			if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1485 				th.CurrentUICulture = prev_appui_culture;
1486 			if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1487 				th.CurrentCulture = prev_app_culture;
1488 
1489 			if (context == null)
1490 				context = HttpContext.Current;
1491 			context.StopTimeoutTimer ();
1492 			context.Request.ReleaseResources ();
1493 			context.Response.ReleaseResources ();
1494 			context = null;
1495 			session = null;
1496 			HttpContext.Current = null;
1497 		}
1498 
Start(object x)1499 		void Start (object x)
1500 		{
1501 			var cultures = x as CultureInfo [];
1502 			if (cultures != null && cultures.Length == 2) {
1503 				Thread ct = Thread.CurrentThread;
1504 				ct.CurrentCulture = cultures [0];
1505 				ct.CurrentUICulture = cultures [1];
1506 			}
1507 
1508 			InitOnce (true);
1509 			if (initialization_exception != null) {
1510 				Exception e = initialization_exception;
1511 				HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
1512 				context.Response.StatusCode = 500;
1513 				FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
1514 				PipelineDone ();
1515 				return;
1516 			}
1517 
1518 			HttpContext.Current = Context;
1519 			PreStart ();
1520 			pipeline = Pipeline ();
1521 			Tick ();
1522 		}
1523 
1524 		const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1525 
GetHandlerCache()1526 		internal static Hashtable GetHandlerCache ()
1527 		{
1528 			Cache cache = HttpRuntime.InternalCache;
1529 			Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1530 
1531 			if (ret == null) {
1532 				ret = new Hashtable ();
1533 				cache.Insert (HANDLER_CACHE, ret);
1534 			}
1535 
1536 			return ret;
1537 		}
1538 
ClearHandlerCache()1539 		internal static void ClearHandlerCache ()
1540 		{
1541 			Hashtable cache = GetHandlerCache ();
1542 			cache.Clear ();
1543 		}
1544 
LocateHandler(HttpRequest req, string verb, string url)1545 		object LocateHandler (HttpRequest req, string verb, string url)
1546 		{
1547 			Hashtable cache = GetHandlerCache ();
1548 			string id = String.Concat (verb, url);
1549 			object ret = cache [id];
1550 
1551 			if (ret != null)
1552 				return ret;
1553 
1554 			bool allowCache;
1555 			HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
1556 			ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
1557 
1558 			IHttpHandler handler = ret as IHttpHandler;
1559 			if (allowCache && handler != null && handler.IsReusable)
1560 				cache [id] = ret;
1561 
1562 			return ret;
1563 		}
1564 
GetHandler(HttpContext context, string url)1565 		internal IHttpHandler GetHandler (HttpContext context, string url)
1566 		{
1567 			return GetHandler (context, url, false);
1568 		}
1569 
1570 		// Used by HttpServerUtility.Execute
GetHandler(HttpContext context, string url, bool ignoreContextHandler)1571 		internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1572 		{
1573 			if (!ignoreContextHandler && context.Handler != null)
1574 				return context.Handler;
1575 
1576 			HttpRequest request = context.Request;
1577 			string verb = request.RequestType;
1578 
1579 			IHttpHandler handler = null;
1580 			object o = LocateHandler (request, verb, url);
1581 
1582 			factory = o as IHttpHandlerFactory;
1583 			if (factory == null) {
1584 				handler = (IHttpHandler) o;
1585 			} else {
1586 				handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1587 			}
1588 
1589 			return handler;
1590 		}
1591 
IHttpHandler.ProcessRequest(HttpContext context)1592 		void IHttpHandler.ProcessRequest (HttpContext context)
1593 		{
1594 			begin_iar = null;
1595 			this.context = context;
1596 			done.Reset ();
1597 
1598 			Start (null);
1599 			done.WaitOne ();
1600 		}
1601 
1602 		//
1603 		// This is used by FireOnAppStart, when we init the application
1604 		// as the context is required to be set at that point (the user
1605 		// might call methods that require it on that hook).
1606 		//
SetContext(HttpContext context)1607 		internal void SetContext (HttpContext context)
1608 		{
1609 			this.context = context;
1610 		}
1611 
SetSession(HttpSessionState session)1612 		internal void SetSession (HttpSessionState session)
1613 		{
1614 			this.session = session;
1615 		}
1616 
IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)1617 		IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1618 		{
1619 			this.context = context;
1620 			done.Reset ();
1621 
1622 			begin_iar = new AsyncRequestState (done, cb, extraData);
1623 
1624 			CultureInfo[] cultures = new CultureInfo [2];
1625 			cultures [0] = Thread.CurrentThread.CurrentCulture;
1626 			cultures [1] = Thread.CurrentThread.CurrentUICulture;
1627 
1628 			if (Thread.CurrentThread.IsThreadPoolThread)
1629 				Start (null);
1630 			else
1631 				ThreadPool.QueueUserWorkItem (x => {
1632 					try {
1633 						Start (x);
1634 					} catch (Exception e) {
1635 						Console.Error.WriteLine (e);
1636 					}
1637 				});
1638 
1639 			return begin_iar;
1640 		}
1641 
IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)1642 		void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1643 		{
1644 			if (!result.IsCompleted)
1645 				result.AsyncWaitHandle.WaitOne ();
1646 			begin_iar = null;
1647 		}
1648 
Init()1649 		public virtual void Init ()
1650 		{
1651 		}
1652 
1653 		bool IHttpHandler.IsReusable {
1654 			get {
1655 				return true;
1656 			}
1657 		}
1658 
RegisterModule(Type moduleType)1659 		public static void RegisterModule (Type moduleType)
1660 		{
1661 			HttpRuntimeSection config = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
1662 
1663 			if (!config.AllowDynamicModuleRegistration)
1664 				throw new InvalidOperationException ("The Application has requested to register a dynamic Module, but dynamic module registration is disabled in web.config.");
1665 
1666 			dynamicModuleManeger.Add (moduleType);
1667 		}
1668 
1669 
CreateDynamicModules()1670 		HttpModuleCollection CreateDynamicModules ()
1671 		{
1672 			HttpModuleCollection modules = new HttpModuleCollection ();
1673 
1674 			foreach (var module in dynamicModuleManeger.LockAndGetModules ()) {
1675 				IHttpModule httpModule = CreateModuleInstance (module.Type);
1676 				httpModule.Init (this);
1677 				modules.AddModule (module.Name, httpModule);
1678 			}
1679 			return modules;
1680 		}
1681 
CreateModuleInstance(Type type)1682 		IHttpModule CreateModuleInstance (Type type)
1683 		{
1684 			return (IHttpModule) Activator.CreateInstance (type,
1685 					BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
1686 					null,
1687 					null,
1688 					null);
1689 		}
1690 
1691 #region internals
ClearError()1692 		internal void ClearError ()
1693 		{
1694 			context.ClearError ();
1695 		}
1696 
RedirectErrorPage(string error_page)1697 		bool RedirectErrorPage (string error_page)
1698 		{
1699 			if (context.Request.QueryString ["aspxerrorpath"] != null)
1700 				return false;
1701 
1702 			Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1703 			return true;
1704 		}
1705 
RedirectCustomError(ref HttpException httpEx)1706 		bool RedirectCustomError (ref HttpException httpEx)
1707 		{
1708 			try {
1709 				if (!context.IsCustomErrorEnabledUnsafe)
1710 					return false;
1711 
1712 				CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
1713 				if (config == null) {
1714 					if (context.ErrorPage != null)
1715 						return RedirectErrorPage (context.ErrorPage);
1716 
1717 					return false;
1718 				}
1719 
1720 				CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1721 				string redirect = err == null ? null : err.Redirect;
1722 				if (redirect == null) {
1723 					redirect = context.ErrorPage;
1724 					if (redirect == null)
1725 						redirect = config.DefaultRedirect;
1726 				}
1727 
1728 				if (redirect == null)
1729 					return false;
1730 
1731 				if (config.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite) {
1732 					context.Server.Execute (redirect);
1733 					return true;
1734 				}
1735 
1736 				return RedirectErrorPage (redirect);
1737 			}
1738 			catch (Exception ex) {
1739 				httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
1740 				return false;
1741 			}
1742 		}
1743 #endregion
1744 		internal static string BinDirectory
1745 		{
1746 			get {
1747 				if (binDirectory == null) {
1748 					AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1749 					string baseDir = setup.ApplicationBase;
1750 					string bindir;
1751 
1752 					foreach (string dir in BinDirs) {
1753 						bindir = Path.Combine (baseDir, dir);
1754 						if (!Directory.Exists (bindir))
1755 							continue;
1756 						binDirectory = bindir;
1757 						break;
1758 					}
1759 				}
1760 
1761 				return binDirectory;
1762 			}
1763 		}
1764 
1765 		internal static string[] BinDirectoryAssemblies
1766 		{
1767 			get {
1768 				ArrayList binDlls = null;
1769 				string[] dlls;
1770 
1771 				string bindir = BinDirectory;
1772 				if (bindir != null) {
1773 					binDlls = new ArrayList ();
1774 					dlls = Directory.GetFiles (bindir, "*.dll");
1775 					binDlls.AddRange (dlls);
1776 				}
1777 
1778 				if (binDlls == null)
1779 					return new string[] {};
1780 
1781 				return (string[]) binDlls.ToArray (typeof (string));
1782 			}
1783 		}
1784 
LoadType(string typeName)1785 		internal static Type LoadType (string typeName)
1786 		{
1787 			return LoadType (typeName, false);
1788 		}
1789 
LoadType(string typeName, bool throwOnMissing)1790 		internal static Type LoadType (string typeName, bool throwOnMissing)
1791 		{
1792 			Type type = Type.GetType (typeName);
1793 			if (type != null)
1794 				return type;
1795 
1796 			Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1797 			foreach (Assembly ass in assemblies) {
1798 				type = ass.GetType (typeName, false);
1799 				if (type != null)
1800 					return type;
1801 			}
1802 
1803 			IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1804 			if (tla != null && tla.Count > 0) {
1805 				foreach (Assembly asm in tla) {
1806 					if (asm == null)
1807 						continue;
1808 					type = asm.GetType (typeName, false);
1809 					if (type != null)
1810 						return type;
1811 				}
1812 			}
1813 
1814 			Exception loadException = null;
1815 			try {
1816 				type = null;
1817 				type = LoadTypeFromBin (typeName);
1818 			} catch (Exception ex) {
1819 				loadException = ex;
1820 			}
1821 
1822 			if (type != null)
1823 				return type;
1824 			if (throwOnMissing)
1825 				throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
1826 
1827 			return null;
1828 		}
1829 
LoadType(string typeName, bool throwOnMissing)1830 		internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
1831 		{
1832 			Type ret = LoadType (typeName, throwOnMissing);
1833 
1834 			if (typeof (TBaseType).IsAssignableFrom (ret))
1835 				return ret;
1836 
1837 			if (throwOnMissing)
1838 				throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
1839 
1840 			return null;
1841 		}
1842 
LoadTypeFromBin(string typeName)1843 		internal static Type LoadTypeFromBin (string typeName)
1844 		{
1845 			Type type = null;
1846 
1847 			foreach (string s in BinDirectoryAssemblies) {
1848 				Assembly binA = null;
1849 
1850 				try {
1851 					binA = Assembly.LoadFrom (s);
1852 				} catch (FileLoadException) {
1853 					// ignore
1854 					continue;
1855 				} catch (BadImageFormatException) {
1856 					// ignore
1857 					continue;
1858 				}
1859 
1860 				type = binA.GetType (typeName, false);
1861 				if (type == null)
1862 					continue;
1863 
1864 				return type;
1865 			}
1866 
1867 			return null;
1868 		}
1869 	}
1870 
1871 	//
1872 	// Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1873 	//
1874 	class AsyncRequestState : IAsyncResult {
1875 		AsyncCallback cb;
1876 		object cb_data;
1877 		bool completed;
1878 		ManualResetEvent complete_event = null;
1879 
AsyncRequestState(ManualResetEvent complete_event, AsyncCallback cb, object cb_data)1880 		internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1881 		{
1882 			this.cb = cb;
1883 			this.cb_data = cb_data;
1884 			this.complete_event = complete_event;
1885 		}
1886 
Complete()1887 		internal void Complete ()
1888 		{
1889 			completed = true;
1890 			try {
1891 				//
1892 				// TODO: if this throws an error, we have no way of reporting it
1893 				// Not really too bad, since the only failure might be
1894 				// `HttpRuntime.request_processed'.
1895 				//
1896 				if (cb != null)
1897 					cb (this);
1898 			} catch {
1899 			}
1900 
1901 			complete_event.Set ();
1902 		}
1903 
1904 		public object AsyncState {
1905 			get {
1906 				return cb_data;
1907 			}
1908 		}
1909 
1910 		public bool CompletedSynchronously {
1911 			get {
1912 				return false;
1913 			}
1914 		}
1915 
1916 		public bool IsCompleted {
1917 			get {
1918 				return completed;
1919 			}
1920 		}
1921 
1922 		public WaitHandle AsyncWaitHandle {
1923 			get {
1924 				return complete_event;
1925 			}
1926 		}
1927 	}
1928 
1929 #region Helper classes
1930 
1931 	//
1932 	// A wrapper to keep track of begin/end pairs
1933 	//
1934 	class AsyncInvoker {
1935 		public BeginEventHandler begin;
1936 		public EndEventHandler end;
1937 		public object data;
1938 		HttpApplication app;
1939 		AsyncCallback callback;
1940 
AsyncInvoker(BeginEventHandler bh, EndEventHandler eh, HttpApplication a, object d)1941 		public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, HttpApplication a, object d)
1942 		{
1943 			begin = bh;
1944 			end = eh;
1945 			data = d;
1946 			app = a;
1947 			callback = new AsyncCallback (doAsyncCallback);
1948 		}
1949 
AsyncInvoker(BeginEventHandler bh, EndEventHandler eh, HttpApplication app)1950 		public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, HttpApplication app) : this(bh, eh, app, null) { }
1951 
Invoke(object sender, EventArgs e)1952 		public void Invoke (object sender, EventArgs e)
1953 		{
1954 			IAsyncResult res;
1955 			res = begin (app, e, callback, data);
1956 		}
1957 
doAsyncCallback(IAsyncResult res)1958 		void doAsyncCallback (IAsyncResult res)
1959 		{
1960 			ThreadPool.QueueUserWorkItem ((object ores) => {
1961 				IAsyncResult tres = (IAsyncResult) ores;
1962 				try {
1963 					end (tres);
1964 				} catch (Exception ee) {
1965 					// I tried using ProcessError(), but we only come here frome an Invokation in PipelineDone().
1966 					// Using ProcessError, I still get a blank screen, this way, we at least log the error to console...
1967 					Console.Error.WriteLine (ee.ToString ());
1968 				}
1969 			}, res);
1970 		}
1971 	}
1972 #endregion
1973 }
1974 
1975