In corlib/System.Runtime.InteropServices:
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateParser.cs
1 //
2 // System.Web.UI.TemplateParser
3 //
4 // Authors:
5 //      Duncan Mak (duncan@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
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
31 using System.CodeDom.Compiler;
32 using System.Collections;
33 using System.Globalization;
34 using System.IO;
35 using System.Reflection;
36 using System.Security.Permissions;
37 using System.Web.Compilation;
38 using System.Web.Configuration;
39 using System.Web.Util;
40
41 namespace System.Web.UI {
42
43         // CAS
44         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         public abstract class TemplateParser : BaseParser
47         {
48                 string inputFile;
49                 string text;
50                 string privateBinPath;
51                 Hashtable mainAttributes;
52                 ArrayList dependencies;
53                 ArrayList assemblies;
54                 Hashtable anames;
55                 ArrayList imports;
56                 ArrayList interfaces;
57                 ArrayList scripts;
58                 Type baseType;
59                 bool baseTypeIsGlobal;
60                 string className;
61                 RootBuilder rootBuilder;
62                 bool debug;
63                 string compilerOptions;
64                 string language;
65                 bool strictOn = false;
66                 bool explicitOn = false;
67                 bool linePragmasOn = false;
68                 bool output_cache;
69                 int oc_duration;
70                 string oc_header, oc_custom, oc_param, oc_controls;
71                 bool oc_shared;
72                 OutputCacheLocation oc_location;
73                 CultureInfo invariantCulture = CultureInfo.InvariantCulture;
74 #if NET_2_0
75                 string src;
76                 string partialClassName;
77 #endif
78                 Assembly srcAssembly;
79                 int appAssemblyIndex = -1;
80
81                 internal TemplateParser ()
82                 {
83                         imports = new ArrayList ();
84 #if NET_2_0
85                         AddNamespaces (imports);
86 #else
87                         imports.Add ("System");
88                         imports.Add ("System.Collections");
89                         imports.Add ("System.Collections.Specialized");
90                         imports.Add ("System.Configuration");
91                         imports.Add ("System.Text");
92                         imports.Add ("System.Text.RegularExpressions");
93                         imports.Add ("System.Web");
94                         imports.Add ("System.Web.Caching");
95                         imports.Add ("System.Web.Security");
96                         imports.Add ("System.Web.SessionState");
97                         imports.Add ("System.Web.UI");
98                         imports.Add ("System.Web.UI.WebControls");
99                         imports.Add ("System.Web.UI.HtmlControls");
100 #endif
101
102                         assemblies = new ArrayList ();
103 #if NET_2_0
104                         bool addAssembliesInBin = false;
105                         foreach (AssemblyInfo info in CompilationConfig.Assemblies) {
106                                 if (info.Assembly == "*")
107                                         addAssembliesInBin = true;
108                                 else
109                                         AddAssemblyByName (info.Assembly);
110                         }
111                         if (addAssembliesInBin)
112                                 AddAssembliesInBin ();
113
114                         foreach (NamespaceInfo info in PagesConfig.Namespaces) {
115                                 imports.Add (info.Namespace);
116                         }
117 #else
118                         foreach (string a in CompilationConfig.Assemblies)
119                                 AddAssemblyByName (a);
120                         if (CompilationConfig.AssembliesInBin)
121                                 AddAssembliesInBin ();
122 #endif
123
124                         language = CompilationConfig.DefaultLanguage;
125                 }
126                 
127                 internal void AddApplicationAssembly ()
128                 {
129                         if (Context.ApplicationInstance == null)
130                                 return; // this may happen if we have Global.asax and have
131                                         // controls registered from Web.Config
132                         string location = Context.ApplicationInstance.AssemblyLocation;
133                         if (location != typeof (TemplateParser).Assembly.Location) {
134                                 appAssemblyIndex = assemblies.Add (location);
135                         }
136                 }
137
138                 protected abstract Type CompileIntoType ();
139
140 #if NET_2_0
141                 void AddNamespaces (ArrayList imports)
142                 {
143                         if (BuildManager.HaveResources)
144                                 imports.Add ("System.Resources");
145                         
146                         PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
147                         if (pages == null)
148                                 return;
149
150                         NamespaceCollection namespaces = pages.Namespaces;
151                         if (namespaces == null || namespaces.Count == 0)
152                                 return;
153
154                         foreach (NamespaceInfo nsi in namespaces)
155                                 imports.Add (nsi.Namespace);
156                 }
157 #endif
158                 
159                 internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
160                 {
161                         string realpath = MapPath (src);
162                         if (String.Compare (realpath, inputFile, false, invariantCulture) == 0)
163                                 return;
164                         
165                         if (!File.Exists (realpath))
166                                 throw new ParseException (Location, "Could not find file \"" + realpath + "\".");
167                         string vpath = UrlUtils.Combine (BaseVirtualDir, src);
168                         Type type = null;
169                         AddDependency (realpath);
170                         try {
171                                 ArrayList other_deps = new ArrayList ();
172                                 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
173                                 foreach (string s in other_deps) {
174                                         AddDependency (s);
175                                 }
176                         } catch (ParseException pe) {
177                                 if (this is UserControlParser)
178                                         throw new ParseException (Location, pe.Message, pe);
179                                 throw;
180                         }
181
182                         AddAssembly (type.Assembly, true);
183                         RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
184                 }
185
186                 internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
187                 {
188                         AddImport (ns);
189                         Assembly ass = AddAssemblyByName (assembly);
190                         AddDependency (ass.Location);
191                         RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
192                 }
193
194                 internal virtual void HandleOptions (object obj)
195                 {
196                 }
197
198                 internal static string GetOneKey (Hashtable tbl)
199                 {
200                         foreach (object key in tbl.Keys)
201                                 return key.ToString ();
202
203                         return null;
204                 }
205                 
206                 internal virtual void AddDirective (string directive, Hashtable atts)
207                 {
208                         if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
209                                 if (mainAttributes != null)
210                                         ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
211
212                                 mainAttributes = atts;
213                                 ProcessMainAttributes (mainAttributes);
214                                 return;
215                         }
216
217                         int cmp = String.Compare ("Assembly", directive, true);
218                         if (cmp == 0) {
219                                 string name = GetString (atts, "Name", null);
220                                 string src = GetString (atts, "Src", null);
221
222                                 if (atts.Count > 0)
223                                         ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
224
225                                 if (name == null && src == null)
226                                         ThrowParseException ("You gotta specify Src or Name");
227                                         
228                                 if (name != null && src != null)
229                                         ThrowParseException ("Src and Name cannot be used together");
230
231                                 if (name != null) {
232                                         AddAssemblyByName (name);
233                                 } else {
234                                         GetAssemblyFromSource (src);
235                                 }
236
237                                 return;
238                         }
239
240                         cmp = String.Compare ("Import", directive, true);
241                         if (cmp == 0) {
242                                 string namesp = GetString (atts, "Namespace", null);
243                                 if (atts.Count > 0)
244                                         ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
245                                 
246                                 if (namesp != null && namesp != "")
247                                         AddImport (namesp);
248                                 return;
249                         }
250
251                         cmp = String.Compare ("Implements", directive, true);
252                         if (cmp == 0) {
253                                 string ifacename = GetString (atts, "Interface", "");
254
255                                 if (atts.Count > 0)
256                                         ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
257                                 
258                                 Type iface = LoadType (ifacename);
259                                 if (iface == null)
260                                         ThrowParseException ("Cannot find type " + ifacename);
261
262                                 if (!iface.IsInterface)
263                                         ThrowParseException (iface + " is not an interface");
264
265                                 AddInterface (iface.FullName);
266                                 return;
267                         }
268
269                         cmp = String.Compare ("OutputCache", directive, true);
270                         if (cmp == 0) {
271                                 HttpResponse response = HttpContext.Current.Response;
272                                 if (response != null)
273                                         response.Cache.SetValidUntilExpires (true);
274                                 
275                                 output_cache = true;
276                                 
277                                 if (atts ["Duration"] == null)
278                                         ThrowParseException ("The directive is missing a 'duration' attribute.");
279                                 if (atts ["VaryByParam"] == null)
280                                         ThrowParseException ("This directive is missing a 'VaryByParam' " +
281                                                         "attribute, which should be set to \"none\", \"*\", " +
282                                                         "or a list of name/value pairs.");
283
284                                 foreach (DictionaryEntry entry in atts) {
285                                         string key = (string) entry.Key;
286                                         switch (key.ToLower ()) {
287                                         case "duration":
288                                                 oc_duration = Int32.Parse ((string) entry.Value);
289                                                 if (oc_duration < 1)
290                                                         ThrowParseException ("The 'duration' attribute must be set " +
291                                                                         "to a positive integer value");
292                                                 break;
293                                         case "varybyparam":
294                                                 oc_param = (string) entry.Value;
295                                                 if (String.Compare (oc_param, "none") == 0)
296                                                         oc_param = null;
297                                                 break;
298                                         case "varybyheader":
299                                                 oc_header = (string) entry.Value;
300                                                 break;
301                                         case "varybycustom":
302                                                 oc_custom = (string) entry.Value;
303                                                 break;
304                                         case "location":
305                                                 if (!(this is PageParser))
306                                                         goto default;
307
308                                                 try {
309                                                         oc_location = (OutputCacheLocation) Enum.Parse (
310                                                                 typeof (OutputCacheLocation), (string) entry.Value, true);
311                                                 } catch {
312                                                         ThrowParseException ("The 'location' attribute is case sensitive and " +
313                                                                         "must be one of the following values: Any, Client, " +
314                                                                         "Downstream, Server, None, ServerAndClient.");
315                                                 }
316                                                 break;
317                                         case "varybycontrol":
318                                                 if (this is PageParser)
319                                                         goto default;
320
321                                                 oc_controls = (string) entry.Value;
322                                                 break;
323                                         case "shared":
324                                                 if (this is PageParser)
325                                                         goto default;
326
327                                                 try {
328                                                         oc_shared = Boolean.Parse ((string) entry.Value);
329                                                 } catch {
330                                                         ThrowParseException ("The 'shared' attribute is case sensitive" +
331                                                                         " and must be set to 'true' or 'false'.");
332                                                 }
333                                                 break;
334                                         default:
335                                                 ThrowParseException ("The '" + key + "' attribute is not " +
336                                                                 "supported by the 'Outputcache' directive.");
337                                                 break;
338                                         }
339                                         
340                                 }
341                                 
342                                 return;
343                         }
344
345                         ThrowParseException ("Unknown directive: " + directive);
346                 }
347
348                 internal Type LoadType (string typeName)
349                 {
350                         // First try loaded assemblies, then try assemblies in Bin directory.
351                         Type type = null;
352                         bool seenBin = false;
353                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
354                         foreach (Assembly ass in assemblies) {
355                                 type = ass.GetType (typeName);
356                                 if (type == null)
357                                         continue;
358
359                                 if (Path.GetDirectoryName (ass.Location) != PrivateBinPath) {
360                                         AddAssembly (ass, true);
361                                 } else {
362                                         seenBin = true;
363                                 }
364
365                                 AddDependency (ass.Location);
366                                 return type;
367                         }
368
369                         if (seenBin)
370                                 return null;
371
372                         // Load from bin
373                         if (!Directory.Exists (PrivateBinPath))
374                                 return null;
375
376                         string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
377                         foreach (string s in binDlls) {
378                                 Assembly binA = Assembly.LoadFrom (s);
379                                 type = binA.GetType (typeName);
380                                 if (type == null)
381                                         continue;
382
383                                 AddDependency (binA.Location);
384                                 return type;
385                         }
386
387                         return null;
388                 }
389
390                 void AddAssembliesInBin ()
391                 {
392                         if (!Directory.Exists (PrivateBinPath))
393                                 return;
394
395                         string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
396                         foreach (string s in binDlls)
397                                 assemblies.Add (s);
398                 }
399
400                 internal virtual void AddInterface (string iface)
401                 {
402                         if (interfaces == null)
403                                 interfaces = new ArrayList ();
404
405                         if (!interfaces.Contains (iface))
406                                 interfaces.Add (iface);
407                 }
408                 
409                 internal virtual void AddImport (string namesp)
410                 {
411                         if (imports == null)
412                                 imports = new ArrayList ();
413
414                         if (!imports.Contains (namesp))
415                                 imports.Add (namesp);
416                 }
417
418                 internal virtual void AddSourceDependency (string filename)
419                 {
420                         if (dependencies != null && dependencies.Contains (filename)) {
421                                 ThrowParseException ("Circular file references are not allowed. File: " + filename);
422                         }
423
424                         AddDependency (filename);
425                 }
426
427                 internal virtual void AddDependency (string filename)
428                 {
429                         if (filename == "")
430                                 return;
431
432                         if (dependencies == null)
433                                 dependencies = new ArrayList ();
434
435                         if (!dependencies.Contains (filename))
436                                 dependencies.Add (filename);
437                 }
438                 
439                 internal virtual void AddAssembly (Assembly assembly, bool fullPath)
440                 {
441                         if (assembly.Location == "")
442                                 return;
443
444                         if (anames == null)
445                                 anames = new Hashtable ();
446
447                         string name = assembly.GetName ().Name;
448                         string loc = assembly.Location;
449                         if (fullPath) {
450                                 if (!assemblies.Contains (loc)) {
451                                         assemblies.Add (loc);
452                                 }
453
454                                 anames [name] = loc;
455                                 anames [loc] = assembly;
456                         } else {
457                                 if (!assemblies.Contains (name)) {
458                                         assemblies.Add (name);
459                                 }
460
461                                 anames [name] = assembly;
462                         }
463                 }
464
465                 internal virtual Assembly AddAssemblyByFileName (string filename)
466                 {
467                         Assembly assembly = null;
468                         Exception error = null;
469
470                         try {
471                                 assembly = Assembly.LoadFrom (filename);
472                         } catch (Exception e) { error = e; }
473
474                         if (assembly == null)
475                                 ThrowParseException ("Assembly " + filename + " not found", error);
476
477                         AddAssembly (assembly, true);
478                         return assembly;
479                 }
480
481                 internal virtual Assembly AddAssemblyByName (string name)
482                 {
483                         if (anames == null)
484                                 anames = new Hashtable ();
485
486                         if (anames.Contains (name)) {
487                                 object o = anames [name];
488                                 if (o is string)
489                                         o = anames [o];
490
491                                 return (Assembly) o;
492                         }
493
494                         Assembly assembly = null;
495                         Exception error = null;
496                         if (name.IndexOf (',') != -1) {
497                                 try {
498                                         assembly = Assembly.Load (name);
499                                 } catch (Exception e) { error = e; }
500                         }
501
502                         if (assembly == null) {
503                                 try {
504                                         assembly = Assembly.LoadWithPartialName (name);
505                                 } catch (Exception e) { error = e; }
506                         }
507                         
508                         if (assembly == null)
509                                 ThrowParseException ("Assembly " + name + " not found", error);
510
511                         AddAssembly (assembly, true);
512                         return assembly;
513                 }
514
515                 internal virtual void ProcessMainAttributes (Hashtable atts)
516                 {
517                         atts.Remove ("Description"); // ignored
518 #if NET_1_1
519                         atts.Remove ("CodeBehind");  // ignored
520 #endif
521                         atts.Remove ("AspCompat"); // ignored
522 #if NET_2_0
523                         // these two are ignored for the moment
524                         atts.Remove ("Async");
525                         atts.Remove ("AsyncTimeOut");
526 #endif
527                         
528                         debug = GetBool (atts, "Debug", true);
529                         compilerOptions = GetString (atts, "CompilerOptions", "");
530                         language = GetString (atts, "Language", CompilationConfig.DefaultLanguage);
531                         strictOn = GetBool (atts, "Strict", CompilationConfig.Strict);
532                         explicitOn = GetBool (atts, "Explicit", CompilationConfig.Explicit);
533                         linePragmasOn = GetBool (atts, "LinePragmas", false);
534                         
535                         string inherits = GetString (atts, "Inherits", null);
536 #if NET_2_0
537                         // In ASP 2, the source file is actually integrated with
538                         // the generated file via the use of partial classes. This
539                         // means that the code file has to be confirmed, but not
540                         // used at this point.
541                         src = GetString (atts, "CodeFile", null);
542
543                         if (src != null && inherits != null) {
544                                 // Make sure the source exists
545                                 src = UrlUtils.Combine (BaseVirtualDir, src);
546                                 string realPath = MapPath (src, false);
547                                 if (!File.Exists (realPath))
548                                         ThrowParseException ("File " + src + " not found");
549
550                                 // We are going to create a partial class that shares
551                                 // the same name as the inherits tag, so reset the
552                                 // name. The base type is changed because it is the
553                                 // code file's responsibilty to extend the classes
554                                 // needed.
555                                 partialClassName = inherits;
556
557                                 // Add the code file as an option to the
558                                 // compiler. This lets both files be compiled at once.
559                                 compilerOptions += " \"" + realPath + "\"";
560                         } else if (inherits != null) {
561                                 // We just set the inherits directly because this is a
562                                 // Single-Page model.
563                                 SetBaseType (inherits);
564                         }
565 #else
566                         string src = GetString (atts, "Src", null);
567
568                         if (src != null)
569                                 srcAssembly = GetAssemblyFromSource (src);
570
571                         if (inherits != null)
572                                 SetBaseType (inherits);
573
574                         className = GetString (atts, "ClassName", null);
575                         if (className != null && !CodeGenerator.IsValidLanguageIndependentIdentifier (className))
576                                 ThrowParseException (String.Format ("'{0}' is not valid for 'className'", className));
577 #endif
578
579                         if (atts.Count > 0)
580                                 ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
581                 }
582
583                 internal void SetBaseType (string type)
584                 {
585                         if (type == DefaultBaseTypeName)
586                                 return;
587
588                         Type parent = null;
589                         if (srcAssembly != null)
590                                 parent = srcAssembly.GetType (type);
591
592                         if (parent == null)
593                                 parent = LoadType (type);
594
595                         if (parent == null)
596                                 ThrowParseException ("Cannot find type " + type);
597
598                         if (!DefaultBaseType.IsAssignableFrom (parent))
599                                 ThrowParseException ("The parent type does not derive from " + DefaultBaseType);
600
601                         baseType = parent;
602                         if (parent.FullName.IndexOf ('.') == -1)
603                                 baseTypeIsGlobal = true;
604                 }
605
606                 Assembly GetAssemblyFromSource (string vpath)
607                 {
608                         vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
609                         string realPath = MapPath (vpath, false);
610                         if (!File.Exists (realPath))
611                                 ThrowParseException ("File " + vpath + " not found");
612
613                         AddSourceDependency (realPath);
614
615                         CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies);
616                         if (result.NativeCompilerReturnValue != 0) {
617                                 StreamReader reader = new StreamReader (realPath);
618                                 throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
619                         }
620
621                         AddAssembly (result.CompiledAssembly, true);
622                         return result.CompiledAssembly;
623                 }
624                 
625                 internal abstract Type DefaultBaseType { get; }
626                 internal abstract string DefaultBaseTypeName { get; }
627                 internal abstract string DefaultDirectiveName { get; }
628
629                 internal string InputFile
630                 {
631                         get { return inputFile; }
632                         set { inputFile = value; }
633                 }
634
635 #if NET_2_0
636                 internal bool IsPartial
637                 {
638                         get { return src != null; }
639                 }
640
641                 internal string PartialClassName
642                 {
643                         get { return partialClassName; }
644                 }
645 #endif
646
647                 internal string Text
648                 {
649                         get { return text; }
650                         set { text = value; }
651                 }
652
653                 internal Type BaseType
654                 {
655                         get {
656                                 if (baseType == null)
657                                         baseType = DefaultBaseType;
658
659                                 return baseType;
660                         }
661                 }
662                 
663                 internal bool BaseTypeIsGlobal {
664                         get { return baseTypeIsGlobal; }
665                 }
666                 
667                 internal string ClassName {
668                         get {
669                                 if (className != null)
670                                         return className;
671
672                                 className = Path.GetFileName (inputFile).Replace ('.', '_');
673                                 className = className.Replace ('-', '_'); 
674                                 className = className.Replace (' ', '_');
675
676                                 if (Char.IsDigit(className[0])) {
677                                         className = "_" + className;
678                                 }
679
680                                 return className;
681                         }
682                 }
683
684                 internal string PrivateBinPath {
685                         get {
686                                 if (privateBinPath != null)
687                                         return privateBinPath;
688
689                                 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
690                                 privateBinPath = Path.Combine (setup.ApplicationBase, setup.PrivateBinPath);
691
692                                 return privateBinPath;
693                         }
694                 }
695
696                 internal ArrayList Scripts {
697                         get {
698                                 if (scripts == null)
699                                         scripts = new ArrayList ();
700
701                                 return scripts;
702                         }
703                 }
704
705                 internal ArrayList Imports {
706                         get { return imports; }
707                 }
708
709                 internal ArrayList Assemblies {
710                         get {
711                                 if (appAssemblyIndex != -1) {
712                                         object o = assemblies [appAssemblyIndex];
713                                         assemblies.RemoveAt (appAssemblyIndex);
714                                         assemblies.Add (o);
715                                         appAssemblyIndex = -1;
716                                 }
717
718                                 return assemblies;
719                         }
720                 }
721
722                 internal ArrayList Interfaces {
723                         get { return interfaces; }
724                 }
725
726                 internal RootBuilder RootBuilder {
727                         get { return rootBuilder; }
728                         set { rootBuilder = value; }
729                 }
730
731                 internal ArrayList Dependencies {
732                         get { return dependencies; }
733                         set { dependencies = value; }
734                 }
735
736                 internal string CompilerOptions {
737                         get { return compilerOptions; }
738                 }
739
740                 internal string Language {
741                         get { return language; }
742                 }
743
744                 internal bool StrictOn {
745                         get { return strictOn; }
746                 }
747
748                 internal bool ExplicitOn {
749                         get { return explicitOn; }
750                 }
751                 
752                 internal bool Debug {
753                         get { return debug; }
754                 }
755
756                 internal bool OutputCache {
757                         get { return output_cache; }
758                 }
759
760                 internal int OutputCacheDuration {
761                         get { return oc_duration; }
762                 }
763
764                 internal string OutputCacheVaryByHeader {
765                         get { return oc_header; }
766                 }
767
768                 internal string OutputCacheVaryByCustom {
769                         get { return oc_custom; }
770                 }
771
772                 internal string OutputCacheVaryByControls {
773                         get { return oc_controls; }
774                 }
775                 
776                 internal bool OutputCacheShared {
777                         get { return oc_shared; }
778                 }
779                 
780                 internal OutputCacheLocation OutputCacheLocation {
781                         get { return oc_location; }
782                 }
783
784                 internal string OutputCacheVaryByParam {
785                         get { return oc_param; }
786                 }
787
788 #if NET_2_0
789                 internal PagesSection PagesConfig {
790                         get {
791                                 return WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
792                         }
793                 }
794 #else
795                 internal PagesConfiguration PagesConfig {
796                         get { return PagesConfiguration.GetInstance (Context); }
797                 }
798 #endif
799         }
800 }
801