System.Web.UI.WebControls.IDataBoundItemControl from reference source
[mono.git] / mcs / class / System.Web / System.Web / HttpContext.cs
1 //
2 // System.Web.HttpContext.cs 
3 //
4 // Author:
5 //      Miguel de Icaza (miguel@novell.com)
6 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
7 //      Marek Habersack <mhabersack@novell.com>
8 //
9
10 //
11 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System.Collections;
34 using System.Configuration;
35 using System.Globalization;
36 using System.Runtime.Remoting.Messaging;
37 using System.Security.Permissions;
38 using System.Security.Principal;
39 using System.Threading;
40 using System.Web.Caching;
41 using System.Web.Configuration;
42 using System.Web.SessionState;
43 using System.Web.UI;
44 using System.Web.Util;
45 using System.Reflection;
46 using System.Collections.Generic;
47 using System.IO;
48 using System.Resources;
49 using System.Web.Compilation;
50 using System.Web.Profile;
51 using CustomErrorMode = System.Web.Configuration.CustomErrorsMode;
52
53 namespace System.Web
54 {
55         // CAS - no InheritanceDemand here as the class is sealed
56         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
57         public sealed partial class HttpContext : IServiceProvider
58         {
59                 internal HttpWorkerRequest WorkerRequest;
60                 HttpApplication app_instance;
61                 HttpRequest request;
62                 HttpResponse response;
63                 HttpSessionState session_state;
64                 HttpServerUtility server;
65                 TraceContext trace_context;
66                 IHttpHandler handler;
67                 string error_page;
68                 bool skip_authorization = false;
69                 IPrincipal user;
70                 object errors;
71                 Hashtable items;
72                 object config_timeout;
73                 int timeout_possible;
74                 DateTime time_stamp = DateTime.UtcNow;
75                 Timer timer;
76                 Thread thread;
77                 bool _isProcessingInclude;
78                 
79                 [ThreadStatic]
80                 static ResourceProviderFactory provider_factory;
81
82                 [ThreadStatic]
83                 static DefaultResourceProviderFactory default_provider_factory;
84                 
85                 [ThreadStatic]
86                 static Dictionary <string, IResourceProvider> resource_providers;
87                 
88                 internal static Assembly AppGlobalResourcesAssembly;
89                 ProfileBase profile = null;
90                 LinkedList<IHttpHandler> handlers;
91
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                 
100                 public HttpContext (HttpWorkerRequest wr)
101                 {
102                         WorkerRequest = wr;
103                         request = new HttpRequest (WorkerRequest, this);
104                         response = new HttpResponse (WorkerRequest, this);
105                         SessionStateBehavior = SessionStateBehavior.Default;
106                 }
107
108                 public HttpContext (HttpRequest request, HttpResponse response)
109                 {
110                         this.request = request;
111                         this.response = response;
112                         this.request.Context = this;
113                         this.response.Context = this;
114                         SessionStateBehavior = SessionStateBehavior.Default;
115                 }
116
117                 internal bool IsProcessingInclude {
118                         get { return _isProcessingInclude; }
119                         set { _isProcessingInclude = value; }
120                 }
121
122                 public Exception [] AllErrors {
123                         get {
124                                 if (errors == null)
125                                         return null;
126
127                                 if (errors is Exception){
128                                         Exception [] all = new Exception [1];
129                                         all [0] = (Exception) errors;
130                                         return all;
131                                 } 
132                                 return (Exception []) (((ArrayList) errors).ToArray (typeof (Exception)));
133                         }
134                 }
135
136                 public HttpApplicationState Application {
137                         get {
138                                 return HttpApplicationFactory.ApplicationState;
139                         }
140                 }
141
142                 public HttpApplication ApplicationInstance {
143                         get {
144                                 return app_instance;
145                         }
146
147                         set {
148                                 app_instance = value;
149                         }
150                               
151                 }
152
153                 public Cache Cache {
154                         get {
155                                 return HttpRuntime.Cache;
156                         }
157                 }
158
159                 internal Cache InternalCache {
160                         get {
161                                 return HttpRuntime.InternalCache;
162                         }
163                 }
164                 
165                 //
166                 // The "Current" property is set just after we have constructed it with 
167                 // the 'HttpContext (HttpWorkerRequest)' constructor.
168                 //
169                 public static HttpContext Current {
170                         get {
171                                 return (HttpContext) CallContext.GetData ("c");
172                         }
173
174                         set {
175                                 CallContext.SetData ("c", value);
176                         }
177                 }
178
179                 public Exception Error {
180                         get {
181                                 if (errors == null || (errors is Exception))
182                                         return (Exception) errors;
183                                 return (Exception) (((ArrayList) errors) [0]);
184                         }
185                 }
186
187                 public IHttpHandler Handler {
188                         get {
189                                 return handler;
190                         }
191
192                         set {
193                                 handler = value;
194                         }
195                 }
196
197                 public bool IsCustomErrorEnabled {
198                         get {
199                                 try {
200                                         return IsCustomErrorEnabledUnsafe;
201                                 }
202                                 catch {
203                                         return false;
204                                 }
205                         }
206                 }
207
208                 internal bool IsCustomErrorEnabledUnsafe {
209                         get {
210                                 CustomErrorsSection cfg = (CustomErrorsSection) WebConfigurationManager.GetSection ("system.web/customErrors");
211                                 if (cfg.Mode == CustomErrorMode.On)
212                                         return true;
213
214                                 return (cfg.Mode == CustomErrorMode.RemoteOnly) && !Request.IsLocal;
215                         }
216                 }
217                 public bool IsDebuggingEnabled {
218                         get { return RuntimeHelpers.DebuggingEnabled; }
219                 }
220                 public IDictionary Items {
221                         get {
222                                 if (items == null)
223                                         items = new Hashtable ();
224                                 return items;
225                         }
226                 }
227
228                 public HttpRequest Request {
229                         get {
230                                 return request;
231                         }
232                 }
233
234                 public HttpResponse Response {
235                         get {
236                                 return response;
237                         }
238                 }
239
240                 public HttpServerUtility Server {
241                         get {
242                                 if (server == null)
243                                         server = new HttpServerUtility (this);
244                                 return server;
245                         }
246                 }
247
248                 public HttpSessionState Session {
249                         get {
250                                 return session_state;
251                         }
252                 }
253
254                 public bool SkipAuthorization {
255                         get {
256                                 return skip_authorization;
257                         }
258
259                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
260                         set {
261                                 skip_authorization = value;
262                         }
263                 }
264
265                 public DateTime Timestamp {
266                         get {
267                                 return time_stamp.ToLocalTime ();
268                         }
269                 }
270                 
271                 public TraceContext Trace {
272                         get {
273                                 if (trace_context == null)
274                                         trace_context = new TraceContext (this);
275                                 return trace_context;
276                         }
277                 }
278
279                 public IPrincipal User {
280                         get {
281                                 return user;
282                         }
283
284                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
285                         set {
286                                 user = value;
287                         }
288                 }
289
290                 internal bool MapRequestHandlerDone {
291                         get;
292                         set;
293                 }
294                 
295                 // The two properties below are defined only when the IIS7 integrated mode is used.
296                 // They are useless under Mono
297                 public RequestNotification CurrentNotification {
298                         get { throw new PlatformNotSupportedException ("This property is not supported on Mono.");  }
299                 }
300
301                 public bool IsPostNotification {
302                         get { throw new PlatformNotSupportedException ("This property is not supported on Mono."); }
303                 }
304                 
305                 internal void PushHandler (IHttpHandler handler)
306                 {
307                         if (handler == null)
308                                 return;
309                         if (handlers == null)
310                                 handlers = new LinkedList <IHttpHandler> ();
311                         handlers.AddLast (handler);
312                 }
313
314                 internal void PopHandler ()
315                 {
316                         if (handlers == null || handlers.Count == 0)
317                                 return;
318                         handlers.RemoveLast ();
319                 }
320                 
321                 IHttpHandler GetCurrentHandler ()
322                 {
323                         if (handlers == null || handlers.Count == 0)
324                                 return null;
325                         
326                         return handlers.Last.Value;
327                 }
328
329                 IHttpHandler GetPreviousHandler ()
330                 {
331                         if (handlers == null || handlers.Count <= 1)
332                                 return null;
333                         LinkedListNode <IHttpHandler> previous = handlers.Last.Previous;
334                         if (previous != null)
335                                 return previous.Value;
336                         return null;
337                 }
338                 
339                 public IHttpHandler CurrentHandler {
340                         get { return GetCurrentHandler (); }
341                 }
342
343                 public IHttpHandler PreviousHandler {
344                         get { return GetPreviousHandler (); }
345                 }
346
347                 internal bool ProfileInitialized {
348                         get { return profile != null; }
349                 }
350
351                 public ProfileBase Profile {
352                         get {
353                                 if (profile == null) {
354                                         if (Request.IsAuthenticated)
355                                                 profile = ProfileBase.Create (User.Identity.Name);
356                                         else
357                                                 profile = ProfileBase.Create (Request.AnonymousID, false);
358                                 }
359                                 return profile;
360                         }
361
362                         internal set {
363                                 profile = value;
364                         }
365                 }
366
367                 public void AddError (Exception errorInfo)
368                 {
369                         if (errors == null){
370                                 errors = errorInfo;
371                                 return;
372                         }
373                         ArrayList l;
374                         if (errors is Exception){
375                                 l = new ArrayList ();
376                                 l.Add (errors);
377                                 errors = l;
378                         } else 
379                                 l = (ArrayList) errors;
380                         l.Add (errorInfo);
381                 }
382
383                 internal void ClearError (Exception e)
384                 {
385                         if (errors == e)
386                                 errors = null;
387                 }
388
389                 internal bool HasError (Exception e)
390                 {
391                         if (errors == e)
392                                 return true;
393
394                         return (errors is ArrayList) ?
395                                 ((ArrayList) errors).Contains (e) : false;
396                 }
397
398                 public void ClearError ()
399                 {
400                         errors = null;
401                 }
402
403                 [Obsolete ("The recommended alternative is System.Web.Configuration.WebConfigurationManager.GetWebApplicationSection in System.Web.dll. http://go.microsoft.com/fwlink/?linkid=14202")]
404                 public static object GetAppConfig (string name)
405                 {
406                         object o = ConfigurationSettings.GetConfig (name);
407
408                         return o;
409                 }
410
411                 [Obsolete ("The recommended alternative is System.Web.HttpContext.GetSection in System.Web.dll. http://go.microsoft.com/fwlink/?linkid=14202")]
412                 public object GetConfig (string name)
413                 {
414                         return GetSection (name);
415                 }
416
417                 public static object GetGlobalResourceObject (string classKey, string resourceKey)
418                 {
419                         return GetGlobalResourceObject (classKey, resourceKey, Thread.CurrentThread.CurrentUICulture);
420                 }
421
422                 static bool EnsureProviderFactory ()
423                 {
424                         if (resource_providers == null)
425                                 resource_providers = new Dictionary <string, IResourceProvider> ();
426
427                         if (provider_factory != null)
428                                 return true;
429                         
430                         GlobalizationSection gs = WebConfigurationManager.GetSection ("system.web/globalization") as GlobalizationSection;
431
432                         if (gs == null)
433                                 return false;
434
435                         String rsfTypeName = gs.ResourceProviderFactoryType;
436                         bool usingDefault = false;
437                         if (String.IsNullOrEmpty (rsfTypeName)) {
438                                 usingDefault = true;
439                                 rsfTypeName = typeof (DefaultResourceProviderFactory).AssemblyQualifiedName;
440                         }
441                         
442                         Type rsfType = HttpApplication.LoadType (rsfTypeName, true);
443                         ResourceProviderFactory rpf = Activator.CreateInstance (rsfType) as ResourceProviderFactory;
444                         
445                         if (rpf == null && usingDefault)
446                                 return false;
447
448                         provider_factory = rpf;
449                         if (usingDefault)
450                                 default_provider_factory = rpf as DefaultResourceProviderFactory;
451                         
452                         return true;
453                 }
454                 
455                 internal static IResourceProvider GetResourceProvider (string virtualPath, bool isLocal)
456                 {
457                         if (!EnsureProviderFactory ())
458                                 return null;
459
460                         // TODO: check if it makes sense to cache the providers and, if yes, maybe
461                         // we should expire the entries (or just store them in InternalCache?)
462                         IResourceProvider rp = null;
463                         if (!resource_providers.TryGetValue (virtualPath, out rp)) {
464                                 if (isLocal)
465                                         rp = provider_factory.CreateLocalResourceProvider (virtualPath);
466                                 else
467                                         rp = provider_factory.CreateGlobalResourceProvider (virtualPath);
468                                 
469                                 if (rp == null) {
470                                         if (isLocal)
471                                                 rp = DefaultProviderFactory.CreateLocalResourceProvider (virtualPath);
472                                         else
473                                                 rp = DefaultProviderFactory.CreateGlobalResourceProvider (virtualPath);
474
475                                         if (rp == null)
476                                                 return null;
477                                 }
478                                 
479                                 resource_providers.Add (virtualPath, rp);
480                         }
481
482                         return rp;
483                 }
484
485                 static object GetGlobalObjectFromFactory (string classKey, string resourceKey, CultureInfo culture)
486                 {
487                         // FIXME: Retention of data
488                         IResourceProvider rp = GetResourceProvider (classKey, false);
489                         if (rp == null)
490                                 return null;
491                         
492                         return rp.GetObject (resourceKey, culture);
493                 }
494                 
495                 public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture)
496                 {
497                         return GetGlobalObjectFromFactory ("Resources." + classKey, resourceKey, culture);
498                 }
499
500                 public static object GetLocalResourceObject (string virtualPath, string resourceKey)
501                 {
502                         return GetLocalResourceObject (virtualPath, resourceKey, Thread.CurrentThread.CurrentUICulture);
503                 }
504
505                 static object GetLocalObjectFromFactory (string virtualPath, string resourceKey, CultureInfo culture)
506                 {
507                         IResourceProvider rp = GetResourceProvider (virtualPath, true);
508                         if (rp == null)
509                                 return null;
510                         
511                         return rp.GetObject (resourceKey, culture);
512                 }
513                 
514                 public static object GetLocalResourceObject (string virtualPath, string resourceKey, CultureInfo culture)
515                 {
516                         if (!VirtualPathUtility.IsAbsolute (virtualPath))
517                                 throw new ArgumentException ("The specified virtualPath was not rooted.");
518
519                         return GetLocalObjectFromFactory (virtualPath, resourceKey, culture);
520                 }
521
522                 public object GetSection (string name)
523                 {
524                         return WebConfigurationManager.GetSection (name);
525                 }
526
527                 object IServiceProvider.GetService (Type service)
528                 {
529                         if (service == typeof (HttpWorkerRequest))
530                                 return WorkerRequest;
531
532                         //
533                         // We return everything out of properties in case
534                         // they are dynamically computed in some form in the future.
535                         //
536                         if (service == typeof (HttpApplication))
537                                 return ApplicationInstance;
538
539                         if (service == typeof (HttpRequest))
540                                 return Request;
541
542                         if (service == typeof (HttpResponse))
543                                 return Response;
544
545                         if (service == typeof (HttpSessionState))
546                                 return Session;
547
548                         if (service == typeof (HttpApplicationState))
549                                 return Application;
550
551                         if (service == typeof (IPrincipal))
552                                 return User;
553
554                         if (service == typeof (Cache))
555                                 return Cache;
556
557                         if (service == typeof (HttpContext))
558                                 return Current;
559
560                         if (service == typeof (IHttpHandler))
561                                 return Handler;
562
563                         if (service == typeof (HttpServerUtility))
564                                 return Server;
565                         
566                         if (service == typeof (TraceContext))
567                                 return Trace;
568                         
569                         return null;
570                 }
571
572                 public void RemapHandler (IHttpHandler handler)
573                 {
574                         if (MapRequestHandlerDone)
575                                 throw new InvalidOperationException ("The RemapHandler method was called after the MapRequestHandler event occurred.");
576                         Handler = handler;
577                 }
578                 
579                 public void RewritePath (string path)
580                 {
581                         RewritePath (path, true);
582                 }
583
584                 public void RewritePath (string filePath, string pathInfo, string queryString)
585                 {
586                         RewritePath (filePath, pathInfo, queryString, false);
587                 }
588
589                 public void RewritePath (string path, bool rebaseClientPath)
590                 {
591                         int qmark = path.IndexOf ('?');
592                         if (qmark != -1)
593                                 RewritePath (path.Substring (0, qmark), String.Empty, path.Substring (qmark + 1), rebaseClientPath);
594                         else
595                                 RewritePath (path, null, null, rebaseClientPath);
596                 }
597
598                 public void RewritePath (string filePath, string pathInfo, string queryString, bool setClientFilePath)
599                 {
600                         if (filePath == null)
601                                 throw new ArgumentNullException ("filePath");
602                         if (!VirtualPathUtility.IsValidVirtualPath (filePath))
603                                 throw new HttpException ("'" + HttpUtility.HtmlEncode (filePath) + "' is not a valid virtual path.");
604
605                         filePath = VirtualPathUtility.Canonize (filePath);
606                         bool pathRelative = VirtualPathUtility.IsAppRelative (filePath);
607                         bool pathAbsolute = pathRelative ? false : VirtualPathUtility.IsAbsolute (filePath);
608                         HttpRequest req = Request;
609                         if (req == null)
610                                 return;
611                         
612                         if (pathRelative || pathAbsolute) {
613                                 if (pathRelative)
614                                         filePath = VirtualPathUtility.ToAbsolute (filePath);
615                         } else
616                                 filePath = VirtualPathUtility.AppendTrailingSlash (req.BaseVirtualDir) + filePath;
617                         
618                         if (!StrUtils.StartsWith (filePath, HttpRuntime.AppDomainAppVirtualPath))
619                                 throw new HttpException (404, "The virtual path '" + HttpUtility.HtmlEncode (filePath) + "' maps to another application.", filePath);
620
621                         req.SetCurrentExePath (filePath);
622                         req.SetFilePath (filePath);
623
624                         if (setClientFilePath)
625                                 req.ClientFilePath = filePath;
626                         
627                         // A null pathInfo or queryString is ignored and previous values remain untouched
628                         if (pathInfo != null)
629                                 req.SetPathInfo (pathInfo);
630
631                         if (queryString != null)
632                                 req.QueryStringRaw = queryString;
633                 }
634
635                 public void SetSessionStateBehavior (SessionStateBehavior sessionStateBehavior)
636                 {
637                         SessionStateBehavior = sessionStateBehavior;
638                 }
639                 
640 #region internals
641                 internal void SetSession (HttpSessionState state)
642                 {
643                         session_state = state;
644                 }
645
646                 // URL of a page used for error redirection.
647                 internal string ErrorPage {
648                         get {
649                                 return error_page;
650                         }
651
652                         set {
653                                 error_page = value;
654                         }
655                 }
656
657                 internal TimeSpan ConfigTimeout {
658                         get {
659                                 if (config_timeout == null)
660                                         config_timeout = HttpRuntime.Section.ExecutionTimeout;
661
662                                 return (TimeSpan) config_timeout;
663                         }
664
665                         set {
666                                 config_timeout = value;
667                                 if (timer != null) {
668                                         TimeSpan remaining = value - (DateTime.UtcNow - time_stamp);
669                                         long remaining_ms = Math.Max ((long)remaining.TotalMilliseconds, 0);
670
671                                         // See http://msdn2.microsoft.com/en-us/library/7hs7492w.aspx
672                                         if (remaining_ms > 4294967294)
673                                                 remaining_ms = 4294967294;
674                                         
675                                         timer.Change (remaining_ms, (long)Timeout.Infinite);
676                                 }
677                         }
678                 }
679
680                 internal SessionStateBehavior SessionStateBehavior {
681                         get;
682                         private set;
683                 }
684                 
685                 void TimeoutReached(object state) {
686                         HttpRuntime.QueuePendingRequest (false);
687                         if (Interlocked.CompareExchange (ref timeout_possible, 0, 0) == 0) {
688                                 if (timer != null)
689                                         timer.Change(2000, 0);
690                                 return;                 
691                         }
692                         StopTimeoutTimer();
693                         
694                         thread.Abort (new StepTimeout ());
695                 }
696                 
697                 internal void StartTimeoutTimer() {
698                         thread = Thread.CurrentThread;
699                         timer = new Timer (TimeoutReached, null, (int)ConfigTimeout.TotalMilliseconds, Timeout.Infinite);
700                 }
701                 
702                 internal void StopTimeoutTimer() {
703                         if(timer != null) {
704                                 timer.Dispose ();
705                                 timer = null;
706                         }
707                 }
708
709                 internal bool TimeoutPossible {
710                         get { return (Interlocked.CompareExchange (ref timeout_possible, 1, 1) == 1); }
711                 }
712
713                 internal void BeginTimeoutPossible ()
714                 {
715                         timeout_possible = 1;
716                 }
717
718                 internal void EndTimeoutPossible ()
719                 {
720                         Interlocked.CompareExchange (ref timeout_possible, 0, 1);
721                 }
722 #endregion
723         }
724         
725         class StepTimeout
726         {
727         }
728 }