HttpApplication.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  1. //
  2. // System.Web.HttpApplication.cs
  3. //
  4. // Author:
  5. // Miguel de Icaza ([email protected])
  6. // Gonzalo Paniagua ([email protected])
  7. //
  8. //
  9. // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. // The Application Processing Pipeline.
  31. //
  32. // The Http application pipeline implemented in this file is a
  33. // beautiful thing. The application pipeline invokes a number of
  34. // hooks at various stages of the processing of a request. These
  35. // hooks can be either synchronous or can be asynchronous.
  36. //
  37. // The pipeline must ensure that every step is completed before
  38. // moving to the next step. A trivial thing for synchronous
  39. // hooks, but asynchronous hooks introduce an extra layer of
  40. // complexity: when the hook is invoked, the thread must
  41. // relinquish its control so that the thread can be reused in
  42. // another operation while waiting.
  43. //
  44. // To implement this functionality we used C# iterators manually;
  45. // we drive the pipeline by executing the various hooks from the
  46. // `RunHooks' routine which is an enumerator that will yield the
  47. // value `false' if execution must proceed or `true' if execution
  48. // must be stopped.
  49. //
  50. // By yielding values we can suspend execution of RunHooks.
  51. //
  52. // Special attention must be given to `in_begin' and `must_yield'
  53. // variables. These are used in the case that an async hook
  54. // completes synchronously as its important to not yield in that
  55. // case or we would hang.
  56. //
  57. // Many of Mono modules used to be declared async, but they would
  58. // actually be completely synchronous, this might resurface in the
  59. // future with other modules.
  60. //
  61. // TODO:
  62. // Events Disposed
  63. //
  64. using System.IO;
  65. using System.Collections;
  66. using System.ComponentModel;
  67. using System.Configuration;
  68. using System.Globalization;
  69. using System.Reflection;
  70. using System.Security.Permissions;
  71. using System.Security.Principal;
  72. using System.Threading;
  73. using System.Web.Caching;
  74. using System.Web.Configuration;
  75. using System.Web.SessionState;
  76. using System.Web.UI;
  77. #if TARGET_J2EE
  78. using Mainsoft.Web;
  79. #endif
  80. namespace System.Web {
  81. // CAS
  82. [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  83. [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  84. // attributes
  85. [ToolboxItem(false)]
  86. public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable {
  87. object this_lock = new object();
  88. internal static readonly string [] BinDirs = {"Bin", "bin"};
  89. HttpContext context;
  90. HttpSessionState session;
  91. ISite isite;
  92. // The source, and the exposed API (cache).
  93. HttpModuleCollection modcoll;
  94. string assemblyLocation;
  95. //
  96. // The factory for the handler currently running.
  97. //
  98. IHttpHandlerFactory factory;
  99. //
  100. // Whether the thread culture is to be auto-set.
  101. // Used only in the 2.0 profile, always false for 1.x
  102. //
  103. bool autoCulture;
  104. bool autoUICulture;
  105. //
  106. // Whether the pipeline should be stopped
  107. //
  108. bool stop_processing;
  109. //
  110. // The Pipeline
  111. //
  112. IEnumerator pipeline;
  113. // To flag when we are done processing a request from BeginProcessRequest.
  114. ManualResetEvent done;
  115. // The current IAsyncResult for the running async request handler in the pipeline
  116. AsyncRequestState begin_iar;
  117. // Tracks the current AsyncInvocation being dispatched
  118. AsyncInvoker current_ai;
  119. // We don't use the EventHandlerList here, but derived classes might do
  120. EventHandlerList events;
  121. // Culture and IPrincipal
  122. CultureInfo app_culture;
  123. CultureInfo appui_culture;
  124. CultureInfo prev_app_culture;
  125. CultureInfo prev_appui_culture;
  126. IPrincipal prev_user;
  127. static bool _runningOnWindows;
  128. #if NET_2_0
  129. #if TARGET_J2EE
  130. const string initialization_exception_key = "System.Web.HttpApplication.initialization_exception";
  131. static Exception initialization_exception {
  132. get { return (Exception) AppDomain.CurrentDomain.GetData (initialization_exception_key); }
  133. set { AppDomain.CurrentDomain.SetData (initialization_exception_key, value); }
  134. }
  135. #else
  136. static Exception initialization_exception;
  137. #endif
  138. bool removeConfigurationFromCache;
  139. #endif
  140. //
  141. // These are used to detect the case where the EndXXX method is invoked
  142. // from within the BeginXXXX delegate, so we detect whether we kick the
  143. // pipeline from here, or from the the RunHook routine
  144. //
  145. bool must_yield;
  146. bool in_begin;
  147. static HttpApplication ()
  148. {
  149. PlatformID pid = Environment.OSVersion.Platform;
  150. _runningOnWindows = ((int) pid != 128 && (int) pid != 4);
  151. }
  152. public HttpApplication ()
  153. {
  154. done = new ManualResetEvent (false);
  155. }
  156. internal void InitOnce (bool full_init)
  157. {
  158. lock (this_lock) {
  159. if (modcoll != null)
  160. return;
  161. #if NET_2_0
  162. HttpModulesSection modules;
  163. modules = (HttpModulesSection) WebConfigurationManager.GetSection ("system.web/httpModules", HttpRuntime.AppDomainAppVirtualPath);
  164. #else
  165. ModulesConfiguration modules;
  166. modules = (ModulesConfiguration) HttpContext.GetAppConfig ("system.web/httpModules");
  167. #endif
  168. modcoll = modules.LoadModules (this);
  169. if (full_init) {
  170. HttpApplicationFactory.AttachEvents (this);
  171. Init ();
  172. }
  173. #if NET_2_0
  174. GlobalizationSection cfg;
  175. cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
  176. app_culture = cfg.GetCulture();
  177. autoCulture = cfg.IsAutoCulture;
  178. appui_culture = cfg.GetUICulture();
  179. autoUICulture = cfg.IsAutoUICulture;
  180. #else
  181. GlobalizationConfiguration cfg;
  182. cfg = GlobalizationConfiguration.GetInstance (null);
  183. if (cfg != null) {
  184. app_culture = cfg.Culture;
  185. appui_culture = cfg.UICulture;
  186. }
  187. #endif
  188. }
  189. }
  190. internal string AssemblyLocation {
  191. get {
  192. if (assemblyLocation == null)
  193. assemblyLocation = GetType ().Assembly.Location;
  194. return assemblyLocation;
  195. }
  196. }
  197. #if NET_2_0
  198. internal static Exception InitializationException {
  199. get { return initialization_exception; }
  200. }
  201. #endif
  202. [Browsable (false)]
  203. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  204. public HttpApplicationState Application {
  205. get {
  206. return HttpApplicationFactory.ApplicationState;
  207. }
  208. }
  209. [Browsable (false)]
  210. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  211. public HttpContext Context {
  212. get {
  213. return context;
  214. }
  215. }
  216. protected EventHandlerList Events {
  217. get {
  218. if (events == null)
  219. events = new EventHandlerList ();
  220. return events;
  221. }
  222. }
  223. [Browsable (false)]
  224. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  225. public HttpModuleCollection Modules {
  226. [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
  227. get {
  228. if (modcoll == null)
  229. modcoll = new HttpModuleCollection ();
  230. return modcoll;
  231. }
  232. }
  233. [Browsable (false)]
  234. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  235. public HttpRequest Request {
  236. get {
  237. if (context == null)
  238. throw new HttpException (Locale.GetText ("No context is available."));
  239. if (false == HttpApplicationFactory.ContextAvailable)
  240. throw new HttpException (Locale.GetText ("Request is not available in this context."));
  241. return context.Request;
  242. }
  243. }
  244. [Browsable (false)]
  245. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  246. public HttpResponse Response {
  247. get {
  248. if (context == null)
  249. throw new HttpException (Locale.GetText ("No context is available."));
  250. if (false == HttpApplicationFactory.ContextAvailable)
  251. throw new HttpException (Locale.GetText ("Response is not available in this context."));
  252. return context.Response;
  253. }
  254. }
  255. [Browsable (false)]
  256. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  257. public HttpServerUtility Server {
  258. get {
  259. if (context != null)
  260. return context.Server;
  261. //
  262. // This is so we can get the Server and call a few methods
  263. // which are not context sensitive, see HttpServerUtilityTest
  264. //
  265. return new HttpServerUtility ((HttpContext) null);
  266. }
  267. }
  268. [Browsable (false)]
  269. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  270. public HttpSessionState Session {
  271. get {
  272. // Only used for Session_End
  273. if (session != null)
  274. return session;
  275. if (context == null)
  276. throw new HttpException (Locale.GetText ("No context is available."));
  277. return context.Session;
  278. }
  279. }
  280. [Browsable (false)]
  281. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  282. #if NET_2_0
  283. public ISite Site {
  284. #else
  285. public virtual ISite Site {
  286. #endif
  287. get {
  288. return isite;
  289. }
  290. set {
  291. isite = value;
  292. }
  293. }
  294. [Browsable (false)]
  295. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  296. public IPrincipal User {
  297. get {
  298. if (context == null)
  299. throw new HttpException (Locale.GetText ("No context is available."));
  300. if (context.User == null)
  301. throw new HttpException (Locale.GetText ("No currently authenticated user."));
  302. return context.User;
  303. }
  304. }
  305. public virtual event EventHandler Disposed;
  306. public virtual event EventHandler Error;
  307. public event EventHandler PreSendRequestHeaders;
  308. internal void TriggerPreSendRequestHeaders ()
  309. {
  310. if (PreSendRequestHeaders != null)
  311. PreSendRequestHeaders (this, EventArgs.Empty);
  312. }
  313. public event EventHandler PreSendRequestContent;
  314. internal void TriggerPreSendRequestContent ()
  315. {
  316. if (PreSendRequestContent != null)
  317. PreSendRequestContent (this, EventArgs.Empty);
  318. }
  319. public event EventHandler AcquireRequestState;
  320. public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
  321. {
  322. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  323. AcquireRequestState += new EventHandler (invoker.Invoke);
  324. }
  325. public event EventHandler AuthenticateRequest;
  326. public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  327. {
  328. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  329. AuthenticateRequest += new EventHandler (invoker.Invoke);
  330. }
  331. public event EventHandler AuthorizeRequest;
  332. public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  333. {
  334. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  335. AuthorizeRequest += new EventHandler (invoker.Invoke);
  336. }
  337. public event EventHandler BeginRequest;
  338. public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  339. {
  340. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  341. BeginRequest += new EventHandler (invoker.Invoke);
  342. }
  343. public event EventHandler EndRequest;
  344. public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  345. {
  346. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  347. EndRequest += new EventHandler (invoker.Invoke);
  348. }
  349. public event EventHandler PostRequestHandlerExecute;
  350. public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
  351. {
  352. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  353. PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
  354. }
  355. public event EventHandler PreRequestHandlerExecute;
  356. public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
  357. {
  358. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  359. PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
  360. }
  361. public event EventHandler ReleaseRequestState;
  362. public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
  363. {
  364. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  365. ReleaseRequestState += new EventHandler (invoker.Invoke);
  366. }
  367. public event EventHandler ResolveRequestCache;
  368. public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
  369. {
  370. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  371. ResolveRequestCache += new EventHandler (invoker.Invoke);
  372. }
  373. public event EventHandler UpdateRequestCache;
  374. public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
  375. {
  376. AsyncInvoker invoker = new AsyncInvoker (bh, eh);
  377. UpdateRequestCache += new EventHandler (invoker.Invoke);
  378. }
  379. #if NET_2_0
  380. public event EventHandler PostAuthenticateRequest;
  381. public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  382. {
  383. AddOnPostAuthenticateRequestAsync (bh, eh, null);
  384. }
  385. public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  386. {
  387. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  388. PostAuthenticateRequest += new EventHandler (invoker.Invoke);
  389. }
  390. public event EventHandler PostAuthorizeRequest;
  391. public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  392. {
  393. AddOnPostAuthorizeRequestAsync (bh, eh, null);
  394. }
  395. public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  396. {
  397. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  398. PostAuthorizeRequest += new EventHandler (invoker.Invoke);
  399. }
  400. public event EventHandler PostResolveRequestCache;
  401. public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
  402. {
  403. AddOnPostResolveRequestCacheAsync (bh, eh, null);
  404. }
  405. public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  406. {
  407. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  408. PostResolveRequestCache += new EventHandler (invoker.Invoke);
  409. }
  410. public event EventHandler PostMapRequestHandler;
  411. public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
  412. {
  413. AddOnPostMapRequestHandlerAsync (bh, eh, null);
  414. }
  415. public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  416. {
  417. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  418. PostMapRequestHandler += new EventHandler (invoker.Invoke);
  419. }
  420. public event EventHandler PostAcquireRequestState;
  421. public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
  422. {
  423. AddOnPostAcquireRequestStateAsync (bh, eh, null);
  424. }
  425. public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  426. {
  427. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  428. PostAcquireRequestState += new EventHandler (invoker.Invoke);
  429. }
  430. public event EventHandler PostReleaseRequestState;
  431. public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
  432. {
  433. AddOnPostReleaseRequestStateAsync (bh, eh, null);
  434. }
  435. public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  436. {
  437. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  438. PostReleaseRequestState += new EventHandler (invoker.Invoke);
  439. }
  440. public event EventHandler PostUpdateRequestCache;
  441. public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
  442. {
  443. AddOnPostUpdateRequestCacheAsync (bh, eh, null);
  444. }
  445. public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  446. {
  447. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  448. PostUpdateRequestCache += new EventHandler (invoker.Invoke);
  449. }
  450. //
  451. // The new overloads that take a data parameter
  452. //
  453. public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  454. {
  455. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  456. AcquireRequestState += new EventHandler (invoker.Invoke);
  457. }
  458. public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  459. {
  460. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  461. AuthenticateRequest += new EventHandler (invoker.Invoke);
  462. }
  463. public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  464. {
  465. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  466. AuthorizeRequest += new EventHandler (invoker.Invoke);
  467. }
  468. public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  469. {
  470. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  471. BeginRequest += new EventHandler (invoker.Invoke);
  472. }
  473. public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  474. {
  475. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  476. EndRequest += new EventHandler (invoker.Invoke);
  477. }
  478. public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  479. {
  480. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  481. PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
  482. }
  483. public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  484. {
  485. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  486. PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
  487. }
  488. public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  489. {
  490. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  491. ReleaseRequestState += new EventHandler (invoker.Invoke);
  492. }
  493. public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  494. {
  495. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  496. ResolveRequestCache += new EventHandler (invoker.Invoke);
  497. }
  498. public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
  499. {
  500. AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
  501. UpdateRequestCache += new EventHandler (invoker.Invoke);
  502. }
  503. // Added in 2.0 SP1
  504. // They are for use with the IIS7 integrated mode, but have been added for compatibility
  505. public event EventHandler LogRequest;
  506. public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  507. {
  508. AddOnLogRequestAsync (bh, eh, null);
  509. }
  510. public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
  511. {
  512. AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
  513. LogRequest += new EventHandler (invoker.Invoke);
  514. }
  515. public event EventHandler MapRequestHandler;
  516. public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
  517. {
  518. AddOnMapRequestHandlerAsync (bh, eh, null);
  519. }
  520. public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
  521. {
  522. AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
  523. MapRequestHandler += new EventHandler (invoker.Invoke);
  524. }
  525. public event EventHandler PostLogRequest;
  526. public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
  527. {
  528. AddOnPostLogRequestAsync (bh, eh, null);
  529. }
  530. public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
  531. {
  532. AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
  533. PostLogRequest += new EventHandler (invoker.Invoke);
  534. }
  535. #endif
  536. internal event EventHandler DefaultAuthentication;
  537. //
  538. // Bypass all the event on the Http pipeline and go directly to EndRequest
  539. //
  540. public void CompleteRequest ()
  541. {
  542. stop_processing = true;
  543. }
  544. internal bool RequestCompleted {
  545. set { stop_processing = value; }
  546. }
  547. public virtual void Dispose ()
  548. {
  549. if (modcoll != null) {
  550. for (int i = modcoll.Count - 1; i >= 0; i--) {
  551. modcoll.Get (i).Dispose ();
  552. }
  553. modcoll = null;
  554. }
  555. if (Disposed != null)
  556. Disposed (this, EventArgs.Empty);
  557. done.Close ();
  558. done = null;
  559. }
  560. public virtual string GetVaryByCustomString (HttpContext context, string custom)
  561. {
  562. if (custom == null) // Sigh
  563. throw new NullReferenceException ();
  564. if (0 == String.Compare (custom, "browser", true, CultureInfo.InvariantCulture))
  565. return context.Request.Browser.Type;
  566. return null;
  567. }
  568. //
  569. // If we catch an error, queue this error
  570. //
  571. void ProcessError (Exception e)
  572. {
  573. bool first = context.Error == null;
  574. context.AddError (e);
  575. if (first){
  576. if (Error != null){
  577. try {
  578. Error (this, EventArgs.Empty);
  579. } catch (ThreadAbortException){
  580. // This happens on Redirect() or End()
  581. Thread.ResetAbort ();
  582. } catch (Exception ee){
  583. context.AddError (ee);
  584. }
  585. }
  586. }
  587. stop_processing = true;
  588. #if NET_2_0
  589. // we want to remove configuration from the cache in case of
  590. // invalid resource not exists to prevent DOS attack.
  591. HttpException httpEx = e as HttpException;
  592. if (httpEx != null && httpEx.GetHttpCode () == 404) {
  593. removeConfigurationFromCache = true;
  594. }
  595. #endif
  596. }
  597. //
  598. // Ticks the clock: next step on the pipeline.
  599. //
  600. internal void Tick ()
  601. {
  602. try {
  603. if (pipeline.MoveNext ()){
  604. if ((bool)pipeline.Current)
  605. PipelineDone ();
  606. }
  607. } catch (ThreadAbortException taex) {
  608. object obj = taex.ExceptionState;
  609. Thread.ResetAbort ();
  610. stop_processing = true;
  611. if (obj is StepTimeout)
  612. ProcessError (new HttpException ("The request timed out."));
  613. else
  614. PipelineDone ();
  615. } catch (Exception e) {
  616. Console.WriteLine ("Tick caught an exception that has not been propagated:\n" + e);
  617. }
  618. }
  619. void Resume ()
  620. {
  621. if (in_begin)
  622. must_yield = false;
  623. else
  624. Tick ();
  625. }
  626. //
  627. // Invoked when our async callback called from RunHooks completes,
  628. // we restart the pipeline here.
  629. //
  630. void async_callback_completed_cb (IAsyncResult ar)
  631. {
  632. if (current_ai.end != null){
  633. try {
  634. current_ai.end (ar);
  635. } catch (Exception e) {
  636. ProcessError (e);
  637. }
  638. }
  639. Resume ();
  640. }
  641. void async_handler_complete_cb (IAsyncResult ar)
  642. {
  643. IHttpAsyncHandler async_handler = ((IHttpAsyncHandler) ar.AsyncState);
  644. try {
  645. async_handler.EndProcessRequest (ar);
  646. } catch (Exception e){
  647. ProcessError (e);
  648. }
  649. Resume ();
  650. }
  651. //
  652. // This enumerator yields whether processing must be stopped:
  653. // true: processing of the pipeline must be stopped
  654. // false: processing of the pipeline must not be stopped
  655. //
  656. IEnumerable RunHooks (Delegate list)
  657. {
  658. Delegate [] delegates = list.GetInvocationList ();
  659. foreach (EventHandler d in delegates){
  660. if (d.Target != null && (d.Target is AsyncInvoker)){
  661. current_ai = (AsyncInvoker) d.Target;
  662. try {
  663. must_yield = true;
  664. in_begin = true;
  665. context.BeginTimeoutPossible ();
  666. current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
  667. } catch (ThreadAbortException taex){
  668. object obj = taex.ExceptionState;
  669. Thread.ResetAbort ();
  670. stop_processing = true;
  671. if (obj is StepTimeout)
  672. ProcessError (new HttpException ("The request timed out."));
  673. } catch (Exception e){
  674. ProcessError (e);
  675. } finally {
  676. in_begin = false;
  677. context.EndTimeoutPossible ();
  678. }
  679. //
  680. // If things are still moving forward, yield this
  681. // thread now
  682. //
  683. if (must_yield)
  684. yield return stop_processing;
  685. else if (stop_processing)
  686. yield return true;
  687. } else {
  688. try {
  689. context.BeginTimeoutPossible ();
  690. d (this, EventArgs.Empty);
  691. } catch (ThreadAbortException taex){
  692. object obj = taex.ExceptionState;
  693. Thread.ResetAbort ();
  694. stop_processing = true;
  695. if (obj is StepTimeout)
  696. ProcessError (new HttpException ("The request timed out."));
  697. } catch (Exception e){
  698. ProcessError (e);
  699. } finally {
  700. context.EndTimeoutPossible ();
  701. }
  702. if (stop_processing)
  703. yield return true;
  704. }
  705. }
  706. }
  707. static void FinalErrorWrite (HttpResponse response, string error)
  708. {
  709. try {
  710. response.Write (error);
  711. response.Flush (true);
  712. } catch {
  713. response.Close ();
  714. }
  715. }
  716. void OutputPage ()
  717. {
  718. if (context.Error == null){
  719. try {
  720. context.Response.Flush (true);
  721. } catch (Exception e){
  722. context.AddError (e);
  723. }
  724. }
  725. Exception error = context.Error;
  726. if (error != null){
  727. HttpResponse response = context.Response;
  728. if (!response.HeadersSent){
  729. response.ClearHeaders ();
  730. response.ClearContent ();
  731. if (error is HttpException){
  732. response.StatusCode = ((HttpException)error).GetHttpCode ();
  733. } else {
  734. error = new HttpException ("", error);
  735. response.StatusCode = 500;
  736. }
  737. HttpException httpEx = (HttpException) error;
  738. if (!RedirectCustomError (ref httpEx))
  739. FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
  740. else
  741. response.Flush (true);
  742. } else {
  743. if (!(error is HttpException))
  744. error = new HttpException ("", error);
  745. FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
  746. }
  747. }
  748. }
  749. //
  750. // Invoked at the end of the pipeline execution
  751. //
  752. void PipelineDone ()
  753. {
  754. try {
  755. if (EndRequest != null)
  756. EndRequest (this, EventArgs.Empty);
  757. } catch (Exception e){
  758. ProcessError (e);
  759. }
  760. try {
  761. OutputPage ();
  762. } catch (Exception e) {
  763. Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
  764. } finally {
  765. context.WorkerRequest.EndOfRequest();
  766. if (factory != null && context.Handler != null){
  767. factory.ReleaseHandler (context.Handler);
  768. context.Handler = null;
  769. factory = null;
  770. }
  771. #if NET_2_0
  772. context.PopHandler ();
  773. #endif
  774. // context = null; -> moved to PostDone
  775. pipeline = null;
  776. current_ai = null;
  777. }
  778. PostDone ();
  779. if (begin_iar != null)
  780. begin_iar.Complete ();
  781. else
  782. done.Set ();
  783. }
  784. //
  785. // Events fired as described in `Http Runtime Support, HttpModules,
  786. // Handling Public Events'
  787. //
  788. IEnumerator Pipeline ()
  789. {
  790. if (stop_processing)
  791. yield return true;
  792. if (BeginRequest != null)
  793. foreach (bool stop in RunHooks (BeginRequest))
  794. yield return stop;
  795. if (AuthenticateRequest != null)
  796. foreach (bool stop in RunHooks (AuthenticateRequest))
  797. yield return stop;
  798. if (DefaultAuthentication != null)
  799. foreach (bool stop in RunHooks (DefaultAuthentication))
  800. yield return stop;
  801. #if NET_2_0
  802. if (PostAuthenticateRequest != null)
  803. foreach (bool stop in RunHooks (PostAuthenticateRequest))
  804. yield return stop;
  805. #endif
  806. if (AuthorizeRequest != null)
  807. foreach (bool stop in RunHooks (AuthorizeRequest))
  808. yield return stop;
  809. #if NET_2_0
  810. if (PostAuthorizeRequest != null)
  811. foreach (bool stop in RunHooks (PostAuthorizeRequest))
  812. yield return stop;
  813. #endif
  814. if (ResolveRequestCache != null)
  815. foreach (bool stop in RunHooks (ResolveRequestCache))
  816. yield return stop;
  817. #if NET_2_0
  818. if (PostResolveRequestCache != null)
  819. foreach (bool stop in RunHooks (PostResolveRequestCache))
  820. yield return stop;
  821. // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
  822. if (MapRequestHandler != null)
  823. foreach (bool stop in RunHooks (MapRequestHandler))
  824. yield return stop;
  825. #endif
  826. // Obtain the handler for the request.
  827. IHttpHandler handler = null;
  828. try {
  829. handler = GetHandler (context, context.Request.FilePath);
  830. context.Handler = handler;
  831. #if NET_2_0
  832. context.PushHandler (handler);
  833. #endif
  834. } catch (FileNotFoundException fnf){
  835. if (context.Request.IsLocal)
  836. ProcessError (new HttpException (404, String.Format ("File not found {0}", fnf.FileName), fnf));
  837. else
  838. ProcessError (new HttpException (404, "File not found: " + Path.GetFileName (fnf.FileName)));
  839. } catch (DirectoryNotFoundException dnf){
  840. if (!context.Request.IsLocal)
  841. dnf = null; // Do not "leak" real path information
  842. ProcessError (new HttpException (404, "Directory not found", dnf));
  843. } catch (Exception e) {
  844. ProcessError (e);
  845. }
  846. if (stop_processing)
  847. yield return true;
  848. #if NET_2_0
  849. if (PostMapRequestHandler != null)
  850. foreach (bool stop in RunHooks (PostMapRequestHandler))
  851. yield return stop;
  852. #endif
  853. if (AcquireRequestState != null){
  854. foreach (bool stop in RunHooks (AcquireRequestState))
  855. yield return stop;
  856. }
  857. #if NET_2_0
  858. if (PostAcquireRequestState != null){
  859. foreach (bool stop in RunHooks (PostAcquireRequestState))
  860. yield return stop;
  861. }
  862. #endif
  863. //
  864. // From this point on, we need to ensure that we call
  865. // ReleaseRequestState, so the code below jumps to
  866. // `release:' to guarantee it rather than yielding.
  867. //
  868. if (PreRequestHandlerExecute != null)
  869. foreach (bool stop in RunHooks (PreRequestHandlerExecute))
  870. if (stop)
  871. goto release;
  872. #if TARGET_J2EE
  873. processHandler:
  874. bool doProcessHandler = false;
  875. #endif
  876. try {
  877. context.BeginTimeoutPossible ();
  878. if (handler != null){
  879. IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
  880. if (async_handler != null){
  881. must_yield = true;
  882. in_begin = true;
  883. async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
  884. } else {
  885. must_yield = false;
  886. handler.ProcessRequest (context);
  887. #if TARGET_J2EE
  888. IHttpExtendedHandler extHandler=handler as IHttpExtendedHandler;
  889. doProcessHandler = extHandler != null && !extHandler.IsCompleted;
  890. #endif
  891. }
  892. }
  893. } catch (ThreadAbortException taex){
  894. object obj = taex.ExceptionState;
  895. Thread.ResetAbort ();
  896. stop_processing = true;
  897. if (obj is StepTimeout)
  898. ProcessError (new HttpException ("The request timed out."));
  899. } catch (Exception e){
  900. ProcessError (e);
  901. } finally {
  902. in_begin = false;
  903. context.EndTimeoutPossible ();
  904. }
  905. #if TARGET_J2EE
  906. if (doProcessHandler) {
  907. yield return false;
  908. goto processHandler;
  909. }
  910. #endif
  911. if (must_yield)
  912. yield return stop_processing;
  913. else if (stop_processing)
  914. goto release;
  915. // These are executed after the application has returned
  916. if (PostRequestHandlerExecute != null)
  917. foreach (bool stop in RunHooks (PostRequestHandlerExecute))
  918. if (stop)
  919. goto release;
  920. release:
  921. if (ReleaseRequestState != null){
  922. #pragma warning disable 168
  923. foreach (bool stop in RunHooks (ReleaseRequestState)){
  924. //
  925. // Ignore the stop signal while release the state
  926. //
  927. }
  928. #pragma warning restore 168
  929. }
  930. if (stop_processing)
  931. yield return true;
  932. #if NET_2_0
  933. if (PostReleaseRequestState != null)
  934. foreach (bool stop in RunHooks (PostReleaseRequestState))
  935. yield return stop;
  936. #endif
  937. if (context.Error == null)
  938. context.Response.DoFilter (true);
  939. if (UpdateRequestCache != null)
  940. foreach (bool stop in RunHooks (UpdateRequestCache))
  941. yield return stop;
  942. #if NET_2_0
  943. if (PostUpdateRequestCache != null)
  944. foreach (bool stop in RunHooks (PostUpdateRequestCache))
  945. yield return stop;
  946. if (LogRequest != null)
  947. foreach (bool stop in RunHooks (LogRequest))
  948. yield return stop;
  949. if (PostLogRequest != null)
  950. foreach (bool stop in RunHooks (PostLogRequest))
  951. yield return stop;
  952. #endif
  953. PipelineDone ();
  954. }
  955. internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
  956. {
  957. #if NET_2_0
  958. if (!isAuto)
  959. return culture;
  960. CultureInfo ret = null;
  961. string[] languages = request.UserLanguages;
  962. try {
  963. if (languages != null && languages.Length > 0)
  964. ret = CultureInfo.CreateSpecificCulture (languages[0]);
  965. } catch {
  966. }
  967. if (ret == null)
  968. ret = culture;
  969. return ret;
  970. #else
  971. return culture;
  972. #endif
  973. }
  974. void PreStart ()
  975. {
  976. #if !TARGET_J2EE
  977. context.StartTimeoutTimer ();
  978. #endif
  979. Thread th = Thread.CurrentThread;
  980. if (app_culture != null) {
  981. prev_app_culture = th.CurrentCulture;
  982. CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
  983. if (!new_app_culture.Equals (CultureInfo.InvariantCulture))
  984. th.CurrentCulture = new_app_culture;
  985. }
  986. if (appui_culture != null) {
  987. prev_appui_culture = th.CurrentUICulture;
  988. CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
  989. if (!new_app_culture.Equals (CultureInfo.InvariantCulture))
  990. th.CurrentUICulture = new_app_culture;
  991. }
  992. #if !TARGET_JVM
  993. prev_user = Thread.CurrentPrincipal;
  994. #endif
  995. }
  996. void PostDone ()
  997. {
  998. #if NET_2_0
  999. if (removeConfigurationFromCache) {
  1000. WebConfigurationManager.RemoveConfigurationFromCache (context);
  1001. removeConfigurationFromCache = false;
  1002. }
  1003. #endif
  1004. Thread th = Thread.CurrentThread;
  1005. #if !TARGET_JVM
  1006. if (Thread.CurrentPrincipal != prev_user)
  1007. Thread.CurrentPrincipal = prev_user;
  1008. #endif
  1009. if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
  1010. th.CurrentUICulture = prev_appui_culture;
  1011. if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
  1012. th.CurrentCulture = prev_app_culture;
  1013. #if !TARGET_J2EE
  1014. if (context == null)
  1015. context = HttpContext.Current;
  1016. context.StopTimeoutTimer ();
  1017. #endif
  1018. context = null;
  1019. session = null;
  1020. HttpContext.Current = null;
  1021. }
  1022. void Start (object x)
  1023. {
  1024. try {
  1025. InitOnce (true);
  1026. } catch (Exception e) {
  1027. #if NET_2_0
  1028. initialization_exception = e;
  1029. #endif
  1030. FinalErrorWrite (context.Response, new HttpException ("", e).GetHtmlErrorMessage ());
  1031. PipelineDone ();
  1032. return;
  1033. }
  1034. HttpContext.Current = Context;
  1035. PreStart ();
  1036. pipeline = Pipeline ();
  1037. Tick ();
  1038. }
  1039. const string HANDLER_CACHE = "@@HttpHandlerCache@@";
  1040. internal static Hashtable GetHandlerCache ()
  1041. {
  1042. Cache cache = HttpRuntime.InternalCache;
  1043. Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
  1044. if (ret == null) {
  1045. ret = new Hashtable ();
  1046. cache.Insert (HANDLER_CACHE, ret);
  1047. }
  1048. return ret;
  1049. }
  1050. internal static void ClearHandlerCache ()
  1051. {
  1052. Hashtable cache = GetHandlerCache ();
  1053. cache.Clear ();
  1054. }
  1055. internal object LocateHandler (string verb, string url)
  1056. {
  1057. Hashtable cache = GetHandlerCache ();
  1058. string id = String.Concat (verb, url);
  1059. object ret = cache [id];
  1060. if (ret != null)
  1061. return ret;
  1062. #if NET_2_0
  1063. HttpHandlersSection httpHandlersSection = (HttpHandlersSection) WebConfigurationManager.GetSection ("system.web/httpHandlers");
  1064. ret = httpHandlersSection.LocateHandler (verb, url);
  1065. #else
  1066. HandlerFactoryConfiguration factory_config = (HandlerFactoryConfiguration) HttpContext.GetAppConfig ("system.web/httpHandlers");
  1067. ret = factory_config.LocateHandler (verb, url);
  1068. #endif
  1069. cache [id] = ret;
  1070. return ret;
  1071. }
  1072. // Used by HttpServerUtility.Execute
  1073. internal IHttpHandler GetHandler (HttpContext context,string url)
  1074. {
  1075. HttpRequest request = context.Request;
  1076. string verb = request.RequestType;
  1077. IHttpHandler handler = null;
  1078. object o = LocateHandler (verb, url);
  1079. factory = o as IHttpHandlerFactory;
  1080. if (factory == null) {
  1081. handler = (IHttpHandler) o;
  1082. } else {
  1083. handler = factory.GetHandler (context, verb, url, request.MapPath (url));
  1084. }
  1085. return handler;
  1086. }
  1087. void IHttpHandler.ProcessRequest (HttpContext context)
  1088. {
  1089. begin_iar = null;
  1090. this.context = context;
  1091. done.Reset ();
  1092. Start (null);
  1093. done.WaitOne ();
  1094. }
  1095. //
  1096. // This is used by FireOnAppStart, when we init the application
  1097. // as the context is required to be set at that point (the user
  1098. // might call methods that require it on that hook).
  1099. //
  1100. internal void SetContext (HttpContext context)
  1101. {
  1102. this.context = context;
  1103. }
  1104. internal void SetSession (HttpSessionState session)
  1105. {
  1106. this.session = session;
  1107. }
  1108. IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
  1109. {
  1110. this.context = context;
  1111. done.Reset ();
  1112. begin_iar = new AsyncRequestState (done, cb, extraData);
  1113. #if TARGET_JVM
  1114. if (true)
  1115. #else
  1116. if (Thread.CurrentThread.IsThreadPoolThread)
  1117. #endif
  1118. Start (null);
  1119. else
  1120. ThreadPool.QueueUserWorkItem (new WaitCallback (Start), null);
  1121. return begin_iar;
  1122. }
  1123. void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
  1124. {
  1125. #if TARGET_J2EE
  1126. if (result == null)
  1127. result = begin_iar;
  1128. #endif
  1129. if (!result.IsCompleted)
  1130. result.AsyncWaitHandle.WaitOne ();
  1131. begin_iar = null;
  1132. }
  1133. public virtual void Init ()
  1134. {
  1135. }
  1136. bool IHttpHandler.IsReusable {
  1137. get {
  1138. return true;
  1139. }
  1140. }
  1141. #region internals
  1142. internal void ClearError ()
  1143. {
  1144. context.ClearError ();
  1145. }
  1146. bool RedirectErrorPage (string error_page)
  1147. {
  1148. if (context.Request.QueryString ["aspxerrorpath"] != null)
  1149. return false;
  1150. Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
  1151. return true;
  1152. }
  1153. bool RedirectCustomError (ref HttpException httpEx)
  1154. {
  1155. try {
  1156. if (!context.IsCustomErrorEnabledUnsafe)
  1157. return false;
  1158. #if NET_2_0
  1159. CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
  1160. #else
  1161. CustomErrorsConfig config = null;
  1162. try {
  1163. config = (CustomErrorsConfig) context.GetConfig ("system.web/customErrors");
  1164. } catch { }
  1165. #endif
  1166. if (config == null) {
  1167. if (context.ErrorPage != null)
  1168. return RedirectErrorPage (context.ErrorPage);
  1169. return false;
  1170. }
  1171. #if NET_2_0
  1172. CustomError err = config.Errors [context.Response.StatusCode.ToString()];
  1173. string redirect = err == null ? null : err.Redirect;
  1174. #else
  1175. string redirect = config [context.Response.StatusCode];
  1176. #endif
  1177. if (redirect == null) {
  1178. redirect = context.ErrorPage;
  1179. if (redirect == null)
  1180. redirect = config.DefaultRedirect;
  1181. }
  1182. if (redirect == null)
  1183. return false;
  1184. return RedirectErrorPage (redirect);
  1185. }
  1186. catch (Exception ex) {
  1187. httpEx = new HttpException (500, "", ex);
  1188. return false;
  1189. }
  1190. }
  1191. #endregion
  1192. internal static bool IsRunningOnWindows {
  1193. get { return _runningOnWindows; }
  1194. }
  1195. internal static IEnumerable BinDirectories
  1196. {
  1197. get {
  1198. AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
  1199. string baseDir = setup.ApplicationBase;
  1200. string bindir;
  1201. if (Environment.GetEnvironmentVariable ("MONO_IOMAP") != null || IsRunningOnWindows) {
  1202. bindir = Path.Combine (baseDir, "bin");
  1203. if (Directory.Exists (bindir))
  1204. yield return bindir;
  1205. } else {
  1206. foreach (string dir in BinDirs) {
  1207. bindir = Path.Combine (baseDir, dir);
  1208. if (!Directory.Exists (bindir))
  1209. continue;
  1210. yield return bindir;
  1211. }
  1212. }
  1213. }
  1214. }
  1215. internal static string[] BinDirectoryAssemblies
  1216. {
  1217. get {
  1218. ArrayList binDlls = null;
  1219. string[] dlls;
  1220. foreach (string bindir in BinDirectories) {
  1221. if (binDlls == null)
  1222. binDlls = new ArrayList ();
  1223. dlls = Directory.GetFiles (bindir, "*.dll");
  1224. binDlls.AddRange (dlls);
  1225. }
  1226. if (binDlls == null)
  1227. return new string[] {};
  1228. return (string[])binDlls.ToArray (typeof (string));
  1229. }
  1230. }
  1231. internal static Type LoadType (string typeName)
  1232. {
  1233. return LoadType (typeName, false);
  1234. }
  1235. internal static Type LoadType (string typeName, bool throwOnMissing)
  1236. {
  1237. Type type = Type.GetType (typeName);
  1238. if (type != null)
  1239. return type;
  1240. #if !TARGET_JVM
  1241. Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
  1242. foreach (Assembly ass in assemblies) {
  1243. type = ass.GetType (typeName, false);
  1244. if (type != null)
  1245. return type;
  1246. }
  1247. #if NET_2_0
  1248. IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
  1249. if (tla != null && tla.Count > 0) {
  1250. foreach (Assembly asm in tla) {
  1251. if (asm == null)
  1252. continue;
  1253. type = asm.GetType (typeName, false);
  1254. if (type != null)
  1255. return type;
  1256. }
  1257. }
  1258. #endif
  1259. type = LoadTypeFromBin (typeName);
  1260. if (type != null)
  1261. return type;
  1262. #endif
  1263. if (throwOnMissing)
  1264. throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName));
  1265. return null;
  1266. }
  1267. internal static Type LoadTypeFromBin (string typeName)
  1268. {
  1269. Type type = null;
  1270. foreach (string s in BinDirectoryAssemblies) {
  1271. Assembly binA = Assembly.LoadFrom (s);
  1272. type = binA.GetType (typeName, false);
  1273. if (type == null)
  1274. continue;
  1275. return type;
  1276. }
  1277. return null;
  1278. }
  1279. }
  1280. //
  1281. // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
  1282. //
  1283. class AsyncRequestState : IAsyncResult {
  1284. AsyncCallback cb;
  1285. object cb_data;
  1286. bool completed;
  1287. ManualResetEvent complete_event = null;
  1288. internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
  1289. {
  1290. this.cb = cb;
  1291. this.cb_data = cb_data;
  1292. this.complete_event = complete_event;
  1293. }
  1294. internal void Complete ()
  1295. {
  1296. completed = true;
  1297. try {
  1298. //
  1299. // TODO: if this throws an error, we have no way of reporting it
  1300. // Not really too bad, since the only failure might be
  1301. // `HttpRuntime.request_processed'.
  1302. //
  1303. if (cb != null)
  1304. cb (this);
  1305. } catch {
  1306. }
  1307. complete_event.Set ();
  1308. }
  1309. public object AsyncState {
  1310. get {
  1311. return cb_data;
  1312. }
  1313. }
  1314. public bool CompletedSynchronously {
  1315. get {
  1316. return false;
  1317. }
  1318. }
  1319. public bool IsCompleted {
  1320. get {
  1321. return completed;
  1322. }
  1323. }
  1324. public WaitHandle AsyncWaitHandle {
  1325. get {
  1326. return complete_event;
  1327. }
  1328. }
  1329. }
  1330. #region Helper classes
  1331. //
  1332. // A wrapper to keep track of begin/end pairs
  1333. //
  1334. class AsyncInvoker {
  1335. public BeginEventHandler begin;
  1336. public EndEventHandler end;
  1337. public object data;
  1338. public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
  1339. {
  1340. begin = bh;
  1341. end = eh;
  1342. data = d;
  1343. }
  1344. public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
  1345. {
  1346. begin = bh;
  1347. end = eh;
  1348. }
  1349. public void Invoke (object sender, EventArgs e)
  1350. {
  1351. throw new Exception ("This is just a dummy");
  1352. }
  1353. }
  1354. #endregion
  1355. }