HttpContext.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. //
  2. // System.Web.HttpContext.cs
  3. //
  4. // Author:
  5. // Miguel de Icaza ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Marek Habersack <[email protected]>
  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. using System.Collections;
  32. using System.Configuration;
  33. using System.Globalization;
  34. using System.Runtime.Remoting.Messaging;
  35. using System.Security.Permissions;
  36. using System.Security.Principal;
  37. using System.Threading;
  38. using System.Web.Caching;
  39. using System.Web.Configuration;
  40. using System.Web.SessionState;
  41. using System.Web.UI;
  42. using System.Web.Util;
  43. using System.Reflection;
  44. using System.Collections.Generic;
  45. using System.IO;
  46. using System.Resources;
  47. using System.Web.Compilation;
  48. using System.Web.Profile;
  49. using CustomErrorMode = System.Web.Configuration.CustomErrorsMode;
  50. namespace System.Web
  51. {
  52. // CAS - no InheritanceDemand here as the class is sealed
  53. [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  54. public sealed partial class HttpContext : IServiceProvider
  55. {
  56. internal HttpWorkerRequest WorkerRequest;
  57. HttpApplication app_instance;
  58. HttpRequest request;
  59. HttpResponse response;
  60. HttpSessionState session_state;
  61. HttpServerUtility server;
  62. TraceContext trace_context;
  63. IHttpHandler handler;
  64. string error_page;
  65. bool skip_authorization = false;
  66. IPrincipal user;
  67. object errors;
  68. Hashtable items;
  69. object config_timeout;
  70. int timeout_possible;
  71. DateTime time_stamp = DateTime.UtcNow;
  72. Timer timer;
  73. Thread thread;
  74. bool _isProcessingInclude;
  75. [ThreadStatic]
  76. static ResourceProviderFactory provider_factory;
  77. [ThreadStatic]
  78. static DefaultResourceProviderFactory default_provider_factory;
  79. [ThreadStatic]
  80. static Dictionary <string, IResourceProvider> resource_providers;
  81. #if TARGET_JVM
  82. const string app_global_res_key = "HttpContext.app_global_res_key";
  83. internal static Assembly AppGlobalResourcesAssembly {
  84. get { return (Assembly) AppDomain.CurrentDomain.GetData (app_global_res_key); }
  85. set { AppDomain.CurrentDomain.SetData (app_global_res_key, value); }
  86. }
  87. #else
  88. internal static Assembly AppGlobalResourcesAssembly;
  89. #endif
  90. ProfileBase profile = null;
  91. LinkedList<IHttpHandler> handlers;
  92. static DefaultResourceProviderFactory DefaultProviderFactory {
  93. get {
  94. if (default_provider_factory == null)
  95. default_provider_factory = new DefaultResourceProviderFactory ();
  96. return default_provider_factory;
  97. }
  98. }
  99. public HttpContext (HttpWorkerRequest wr)
  100. {
  101. WorkerRequest = wr;
  102. request = new HttpRequest (WorkerRequest, this);
  103. response = new HttpResponse (WorkerRequest, this);
  104. SessionStateBehavior = SessionStateBehavior.Default;
  105. }
  106. public HttpContext (HttpRequest request, HttpResponse response)
  107. {
  108. this.request = request;
  109. this.response = response;
  110. SessionStateBehavior = SessionStateBehavior.Default;
  111. }
  112. internal bool IsProcessingInclude {
  113. get { return _isProcessingInclude; }
  114. set { _isProcessingInclude = value; }
  115. }
  116. public Exception [] AllErrors {
  117. get {
  118. if (errors == null)
  119. return null;
  120. if (errors is Exception){
  121. Exception [] all = new Exception [1];
  122. all [0] = (Exception) errors;
  123. return all;
  124. }
  125. return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception)));
  126. }
  127. }
  128. public HttpApplicationState Application {
  129. get {
  130. return HttpApplicationFactory.ApplicationState;
  131. }
  132. }
  133. public HttpApplication ApplicationInstance {
  134. get {
  135. return app_instance;
  136. }
  137. set {
  138. app_instance = value;
  139. }
  140. }
  141. public Cache Cache {
  142. get {
  143. return HttpRuntime.Cache;
  144. }
  145. }
  146. internal Cache InternalCache {
  147. get {
  148. return HttpRuntime.InternalCache;
  149. }
  150. }
  151. //
  152. // The "Current" property is set just after we have constructed it with
  153. // the 'HttpContext (HttpWorkerRequest)' constructor.
  154. //
  155. #if !TARGET_JVM // No remoting CallContext support in Grasshopper
  156. public static HttpContext Current {
  157. get {
  158. return (HttpContext) CallContext.GetData ("c");
  159. }
  160. set {
  161. CallContext.SetData ("c", value);
  162. }
  163. }
  164. #endif
  165. public Exception Error {
  166. get {
  167. if (errors == null || (errors is Exception))
  168. return (Exception) errors;
  169. return (Exception) (((ArrayList) errors) [0]);
  170. }
  171. }
  172. public IHttpHandler Handler {
  173. get {
  174. return handler;
  175. }
  176. set {
  177. handler = value;
  178. }
  179. }
  180. public bool IsCustomErrorEnabled {
  181. get {
  182. try {
  183. return IsCustomErrorEnabledUnsafe;
  184. }
  185. catch {
  186. return false;
  187. }
  188. }
  189. }
  190. internal bool IsCustomErrorEnabledUnsafe {
  191. get {
  192. CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors");
  193. if (cfg.Mode == CustomErrorMode.On)
  194. return true;
  195. return (cfg.Mode == CustomErrorMode.RemoteOnly) && !Request.IsLocal;
  196. }
  197. }
  198. #if !TARGET_JVM
  199. public bool IsDebuggingEnabled {
  200. get { return HttpRuntime.IsDebuggingEnabled; }
  201. }
  202. #endif
  203. public IDictionary Items {
  204. get {
  205. if (items == null)
  206. items = new Hashtable ();
  207. return items;
  208. }
  209. }
  210. public HttpRequest Request {
  211. get {
  212. return request;
  213. }
  214. }
  215. public HttpResponse Response {
  216. get {
  217. return response;
  218. }
  219. }
  220. public HttpServerUtility Server {
  221. get {
  222. if (server == null)
  223. server = new HttpServerUtility (this);
  224. return server;
  225. }
  226. }
  227. public HttpSessionState Session {
  228. get {
  229. return session_state;
  230. }
  231. }
  232. public bool SkipAuthorization {
  233. get {
  234. return skip_authorization;
  235. }
  236. [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
  237. set {
  238. skip_authorization = value;
  239. }
  240. }
  241. public DateTime Timestamp {
  242. get {
  243. return time_stamp.ToLocalTime ();
  244. }
  245. }
  246. public TraceContext Trace {
  247. get {
  248. if (trace_context == null)
  249. trace_context = new TraceContext (this);
  250. return trace_context;
  251. }
  252. }
  253. public IPrincipal User {
  254. get {
  255. return user;
  256. }
  257. [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
  258. set {
  259. user = value;
  260. }
  261. }
  262. internal bool MapRequestHandlerDone {
  263. get;
  264. set;
  265. }
  266. // The two properties below are defined only when the IIS7 integrated mode is used.
  267. // They are useless under Mono
  268. public RequestNotification CurrentNotification {
  269. get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); }
  270. }
  271. public bool IsPostNotification {
  272. get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); }
  273. }
  274. internal void PushHandler (IHttpHandler handler)
  275. {
  276. if (handler == null)
  277. return;
  278. if (handlers == null)
  279. handlers = new LinkedList <IHttpHandler> ();
  280. handlers.AddLast (handler);
  281. }
  282. internal void PopHandler ()
  283. {
  284. if (handlers == null || handlers.Count == 0)
  285. return;
  286. handlers.RemoveLast ();
  287. }
  288. IHttpHandler GetCurrentHandler ()
  289. {
  290. if (handlers == null || handlers.Count == 0)
  291. return null;
  292. return handlers.Last.Value;
  293. }
  294. IHttpHandler GetPreviousHandler ()
  295. {
  296. if (handlers == null || handlers.Count <= 1)
  297. return null;
  298. LinkedListNode <IHttpHandler> previous = handlers.Last.Previous;
  299. if (previous != null)
  300. return previous.Value;
  301. return null;
  302. }
  303. public IHttpHandler CurrentHandler {
  304. get { return GetCurrentHandler (); }
  305. }
  306. public IHttpHandler PreviousHandler {
  307. get { return GetPreviousHandler (); }
  308. }
  309. internal bool ProfileInitialized {
  310. get { return profile != null; }
  311. }
  312. public ProfileBase Profile {
  313. get {
  314. if (profile == null) {
  315. if (Request.IsAuthenticated)
  316. profile = ProfileBase.Create (User.Identity.Name);
  317. else
  318. profile = ProfileBase.Create (Request.AnonymousID, false);
  319. }
  320. return profile;
  321. }
  322. internal set {
  323. profile = value;
  324. }
  325. }
  326. public void AddError (Exception errorInfo)
  327. {
  328. if (errors == null){
  329. errors = errorInfo;
  330. return;
  331. }
  332. ArrayList l;
  333. if (errors is Exception){
  334. l = new ArrayList ();
  335. l.Add (errors);
  336. errors = l;
  337. } else
  338. l = (ArrayList) errors;
  339. l.Add (errorInfo);
  340. }
  341. internal void ClearError (Exception e)
  342. {
  343. if (errors == e)
  344. errors = null;
  345. }
  346. internal bool HasError (Exception e)
  347. {
  348. if (errors == e)
  349. return true;
  350. return (errors is ArrayList) ?
  351. ((ArrayList) errors).Contains (e) : false;
  352. }
  353. public void ClearError ()
  354. {
  355. errors = null;
  356. }
  357. [Obsolete ("use WebConfigurationManager.GetWebApplicationSection")]
  358. public static object GetAppConfig (string name)
  359. {
  360. object o = ConfigurationSettings.GetConfig (name);
  361. return o;
  362. }
  363. [Obsolete ("see GetSection")]
  364. public object GetConfig (string name)
  365. {
  366. return GetSection (name);
  367. }
  368. public static object GetGlobalResourceObject (string classKey, string resourceKey)
  369. {
  370. return GetGlobalResourceObject (classKey, resourceKey, Thread.CurrentThread.CurrentUICulture);
  371. }
  372. static bool EnsureProviderFactory ()
  373. {
  374. if (resource_providers == null)
  375. resource_providers = new Dictionary <string, IResourceProvider> ();
  376. if (provider_factory != null)
  377. return true;
  378. GlobalizationSection gs = WebConfigurationManager.GetSection ("system.web/globalization") as GlobalizationSection;
  379. if (gs == null)
  380. return false;
  381. String rsfTypeName = gs.ResourceProviderFactoryType;
  382. bool usingDefault = false;
  383. if (String.IsNullOrEmpty (rsfTypeName)) {
  384. usingDefault = true;
  385. rsfTypeName = typeof (DefaultResourceProviderFactory).AssemblyQualifiedName;
  386. }
  387. Type rsfType = HttpApplication.LoadType (rsfTypeName, true);
  388. ResourceProviderFactory rpf = Activator.CreateInstance (rsfType) as ResourceProviderFactory;
  389. if (rpf == null && usingDefault)
  390. return false;
  391. provider_factory = rpf;
  392. if (usingDefault)
  393. default_provider_factory = rpf as DefaultResourceProviderFactory;
  394. return true;
  395. }
  396. internal static IResourceProvider GetResourceProvider (string virtualPath, bool isLocal)
  397. {
  398. if (!EnsureProviderFactory ())
  399. return null;
  400. // TODO: check if it makes sense to cache the providers and, if yes, maybe
  401. // we should expire the entries (or just store them in InternalCache?)
  402. IResourceProvider rp = null;
  403. if (!resource_providers.TryGetValue (virtualPath, out rp)) {
  404. if (isLocal) {
  405. HttpContext ctx = HttpContext.Current;
  406. HttpRequest req = ctx != null ? ctx.Request : null;
  407. rp = provider_factory.CreateLocalResourceProvider (virtualPath);
  408. } else
  409. rp = provider_factory.CreateGlobalResourceProvider (virtualPath);
  410. if (rp == null) {
  411. if (isLocal) {
  412. HttpContext ctx = HttpContext.Current;
  413. HttpRequest req = ctx != null ? ctx.Request : null;
  414. rp = DefaultProviderFactory.CreateLocalResourceProvider (virtualPath);
  415. } else
  416. rp = DefaultProviderFactory.CreateGlobalResourceProvider (virtualPath);
  417. if (rp == null)
  418. return null;
  419. }
  420. resource_providers.Add (virtualPath, rp);
  421. }
  422. return rp;
  423. }
  424. static object GetGlobalObjectFromFactory (string classKey, string resourceKey, CultureInfo culture)
  425. {
  426. // FIXME: Retention of data
  427. IResourceProvider rp = GetResourceProvider (classKey, false);
  428. if (rp == null)
  429. return null;
  430. return rp.GetObject (resourceKey, culture);
  431. }
  432. public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture)
  433. {
  434. return GetGlobalObjectFromFactory ("Resources." + classKey, resourceKey, culture);
  435. }
  436. public static object GetLocalResourceObject (string virtualPath, string resourceKey)
  437. {
  438. return GetLocalResourceObject (virtualPath, resourceKey, Thread.CurrentThread.CurrentUICulture);
  439. }
  440. static object GetLocalObjectFromFactory (string virtualPath, string resourceKey, CultureInfo culture)
  441. {
  442. IResourceProvider rp = GetResourceProvider (virtualPath, true);
  443. if (rp == null)
  444. return null;
  445. return rp.GetObject (resourceKey, culture);
  446. }
  447. public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture)
  448. {
  449. if (!VirtualPathUtility.IsAbsolute (virtualPath))
  450. throw new ArgumentException ("The specified virtualPath was not rooted.");
  451. return GetLocalObjectFromFactory (virtualPath, resourceKey, culture);
  452. }
  453. public object GetSection (string name)
  454. {
  455. return WebConfigurationManager.GetSection (name);
  456. }
  457. object IServiceProvider.GetService (Type service)
  458. {
  459. if (service == typeof (HttpWorkerRequest))
  460. return WorkerRequest;
  461. //
  462. // We return everything out of properties in case
  463. // they are dynamically computed in some form in the future.
  464. //
  465. if (service == typeof (HttpApplication))
  466. return ApplicationInstance;
  467. if (service == typeof (HttpRequest))
  468. return Request;
  469. if (service == typeof (HttpResponse))
  470. return Response;
  471. if (service == typeof (HttpSessionState))
  472. return Session;
  473. if (service == typeof (HttpApplicationState))
  474. return Application;
  475. if (service == typeof (IPrincipal))
  476. return User;
  477. if (service == typeof (Cache))
  478. return Cache;
  479. if (service == typeof (HttpContext))
  480. return Current;
  481. if (service == typeof (IHttpHandler))
  482. return Handler;
  483. if (service == typeof (HttpServerUtility))
  484. return Server;
  485. if (service == typeof (TraceContext))
  486. return Trace;
  487. return null;
  488. }
  489. public void RemapHandler (IHttpHandler handler)
  490. {
  491. if (MapRequestHandlerDone)
  492. throw new InvalidOperationException ("The RemapHandler method was called after the MapRequestHandler event occurred.");
  493. Handler = handler;
  494. }
  495. public void RewritePath (string path)
  496. {
  497. RewritePath (path, true);
  498. }
  499. public void RewritePath (string filePath, string pathInfo, string queryString)
  500. {
  501. RewritePath (filePath, pathInfo, queryString, false);
  502. }
  503. public void RewritePath (string path, bool rebaseClientPath)
  504. {
  505. int qmark = path.IndexOf ('?');
  506. if (qmark != -1)
  507. RewritePath (path.Substring (0, qmark), String.Empty, path.Substring (qmark + 1), rebaseClientPath);
  508. else
  509. RewritePath (path, null, null, rebaseClientPath);
  510. }
  511. public void RewritePath (string filePath, string pathInfo, string queryString, bool setClientFilePath)
  512. {
  513. if (filePath == null)
  514. throw new ArgumentNullException ("filePath");
  515. if (!VirtualPathUtility.IsValidVirtualPath (filePath))
  516. throw new HttpException ("'" + HttpUtility.HtmlEncode (filePath) + "' is not a valid virtual path.");
  517. bool pathRelative = VirtualPathUtility.IsAppRelative (filePath);
  518. bool pathAbsolute = pathRelative ? false : VirtualPathUtility.IsAbsolute (filePath);
  519. HttpRequest req = Request;
  520. if (req == null)
  521. return;
  522. if (pathRelative || pathAbsolute) {
  523. if (pathRelative)
  524. filePath = VirtualPathUtility.ToAbsolute (filePath);
  525. else
  526. filePath = filePath;
  527. } else
  528. filePath = VirtualPathUtility.AppendTrailingSlash (req.BaseVirtualDir) + filePath;
  529. if (!StrUtils.StartsWith (filePath, HttpRuntime.AppDomainAppVirtualPath))
  530. throw new HttpException (404, "The virtual path '" + HttpUtility.HtmlEncode (filePath) + "' maps to another application.", filePath);
  531. req.SetCurrentExePath (filePath);
  532. req.SetFilePath (filePath);
  533. if (setClientFilePath)
  534. req.ClientFilePath = filePath;
  535. // A null pathInfo or queryString is ignored and previous values remain untouched
  536. if (pathInfo != null)
  537. req.SetPathInfo (pathInfo);
  538. if (queryString != null)
  539. req.QueryStringRaw = queryString;
  540. }
  541. #if NET_4_0
  542. public void SetSessionStateBehavior (SessionStateBehavior sessionStateBehavior)
  543. {
  544. SessionStateBehavior = sessionStateBehavior;
  545. }
  546. #endif
  547. #region internals
  548. internal void SetSession (HttpSessionState state)
  549. {
  550. session_state = state;
  551. }
  552. // URL of a page used for error redirection.
  553. internal string ErrorPage {
  554. get {
  555. return error_page;
  556. }
  557. set {
  558. error_page = value;
  559. }
  560. }
  561. internal TimeSpan ConfigTimeout {
  562. get {
  563. if (config_timeout == null) {
  564. HttpRuntimeSection section = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
  565. config_timeout = section.ExecutionTimeout;
  566. }
  567. return (TimeSpan) config_timeout;
  568. }
  569. set {
  570. config_timeout = value;
  571. #if !TARGET_J2EE
  572. if (timer != null) {
  573. TimeSpan remaining = value - (DateTime.UtcNow - time_stamp);
  574. long remaining_ms = Math.Max ((long)remaining.TotalMilliseconds, 0);
  575. // See http://msdn2.microsoft.com/en-us/library/7hs7492w.aspx
  576. if (remaining_ms > 4294967294)
  577. remaining_ms = 4294967294;
  578. timer.Change (remaining_ms, (long)Timeout.Infinite);
  579. }
  580. #endif
  581. }
  582. }
  583. #if NET_4_0
  584. internal SessionStateBehavior SessionStateBehavior {
  585. get;
  586. private set;
  587. }
  588. #endif
  589. #if !TARGET_J2EE
  590. void TimeoutReached(object state) {
  591. HttpRuntime.QueuePendingRequest (false);
  592. if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) {
  593. timer.Change(2000, 0);
  594. return;
  595. }
  596. StopTimeoutTimer();
  597. thread.Abort (new StepTimeout ());
  598. }
  599. internal void StartTimeoutTimer() {
  600. thread = Thread.CurrentThread;
  601. timer = new Timer (TimeoutReached, null, (int)ConfigTimeout.TotalMilliseconds, Timeout.Infinite);
  602. }
  603. internal void StopTimeoutTimer() {
  604. if(timer != null) {
  605. timer.Dispose ();
  606. timer = null;
  607. }
  608. }
  609. internal bool TimeoutPossible {
  610. get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); }
  611. }
  612. internal void BeginTimeoutPossible ()
  613. {
  614. timeout_possible = 1;
  615. }
  616. internal void EndTimeoutPossible ()
  617. {
  618. Interlocked.CompareExchange (ref timeout_possible, 0, 1);
  619. }
  620. #endif
  621. #endregion
  622. }
  623. class StepTimeout
  624. {
  625. }
  626. }