copied mono-api-diff.cs from mono-2-2 branch so new patch can be applied and history...
[mono.git] / mcs / class / System.Web / System.Web.UI / PageParser.cs
1 //      
2 // System.Web.UI.PageParser
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
8 // Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.Globalization;
33 using System.Security.Permissions;
34 using System.Text;
35 using System.Web.Compilation;
36 using System.Web.Configuration;
37 using System.Web.Hosting;
38 using System.Web.Util;
39 using System.IO;
40
41 namespace System.Web.UI
42 {
43         // CAS - no InheritanceDemand here as the class is sealed
44         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45         public sealed class PageParser : TemplateControlParser
46         {
47                 PagesEnableSessionState enableSessionState = PagesEnableSessionState.True;
48                 bool enableViewStateMac;
49                 bool enableViewStateMacSet;
50                 bool smartNavigation;
51                 bool haveTrace;
52                 bool trace;
53                 bool notBuffer;
54                 TraceMode tracemode = TraceMode.Default;
55                 string responseEncoding;
56                 string contentType;
57                 int codepage = -1;
58                 int lcid = -1;
59                 string culture;
60                 string uiculture;
61                 string errorPage;
62                 bool validateRequest;
63                 string clientTarget;
64                 bool async;
65                 int asyncTimeout = -1;
66                 string masterPage;
67                 Type masterType;
68                 string masterVirtualPath;
69                 string title;
70                 string theme;
71                 string styleSheetTheme;
72                 bool enable_event_validation;
73                 bool maintainScrollPositionOnPostBack;
74                 int maxPageStateFieldLength = -1;
75                 Type previousPageType;
76                 string previousPageVirtualPath;
77
78                 public PageParser ()
79                 {
80                         LoadConfigDefaults ();
81                 }
82                 
83                 internal PageParser (string virtualPath, string inputFile, HttpContext context)
84                 {
85                         this.VirtualPath = new VirtualPath (virtualPath);
86                         Context = context;
87                         BaseVirtualDir = VirtualPathUtility.GetDirectory (virtualPath, false);
88                         InputFile = inputFile;
89                         SetBaseType (null);
90                         AddApplicationAssembly ();
91                         LoadConfigDefaults ();
92                 }
93
94                 internal PageParser (VirtualPath virtualPath, TextReader reader, HttpContext context)
95                         : this (virtualPath, null, reader, context)
96                 {
97                 }
98                 
99                 internal PageParser (VirtualPath virtualPath, string inputFile, TextReader reader, HttpContext context)
100                 {
101                         this.VirtualPath = virtualPath;
102                         Context = context;
103                         BaseVirtualDir = virtualPath.DirectoryNoNormalize;
104                         Reader = reader;
105                         if (String.IsNullOrEmpty (inputFile))
106                                 InputFile = virtualPath.PhysicalPath;
107                         else
108                                 InputFile = inputFile;
109                         SetBaseType (null);
110                         AddApplicationAssembly ();
111                         LoadConfigDefaults ();
112                 }
113
114                 internal override void LoadConfigDefaults ()
115                 {
116                         base.LoadConfigDefaults ();
117                         PagesSection ps = PagesConfig;
118
119                         notBuffer = !ps.Buffer;
120                         enableSessionState = ps.EnableSessionState;
121                         enableViewStateMac = ps.EnableViewStateMac;
122                         smartNavigation = ps.SmartNavigation;
123                         validateRequest = ps.ValidateRequest;
124                         masterPage = ps.MasterPageFile;
125                         if (masterPage.Length == 0)
126                                 masterPage = null;
127                         enable_event_validation = ps.EnableEventValidation;
128                         maxPageStateFieldLength = ps.MaxPageStateFieldLength;
129                         theme = ps.Theme;
130                         if (theme.Length == 0)
131                                 theme = null;
132                         styleSheetTheme = ps.StyleSheetTheme;
133                         if (styleSheetTheme.Length == 0)
134                                 styleSheetTheme = null;
135                         maintainScrollPositionOnPostBack = ps.MaintainScrollPositionOnPostBack;
136                 }
137                 
138                 public static IHttpHandler GetCompiledPageInstance (string virtualPath, string inputFile, HttpContext context)
139                 {
140                         bool isFake = false;
141
142                         if (!String.IsNullOrEmpty (inputFile))
143                                 isFake = !inputFile.StartsWith (HttpRuntime.AppDomainAppPath);
144                         
145                         return BuildManager.CreateInstanceFromVirtualPath (new VirtualPath (virtualPath, inputFile, isFake), typeof (IHttpHandler)) as IHttpHandler;
146                 }
147                 
148                 internal override void ProcessMainAttributes (Hashtable atts)
149                 {
150                         // note: the 'enableSessionState' configuration property is
151                         // processed in a case-sensitive manner while the page-level
152                         // attribute is processed case-insensitive
153                         string enabless = GetString (atts, "EnableSessionState", null);
154                         if (enabless != null) {
155                                 if (String.Compare (enabless, "readonly", true, Helpers.InvariantCulture) == 0)
156                                         enableSessionState = PagesEnableSessionState.ReadOnly;
157                                 else if (String.Compare (enabless, "true", true, Helpers.InvariantCulture) == 0)
158                                         enableSessionState = PagesEnableSessionState.True;
159                                 else if (String.Compare (enabless, "false", true, Helpers.InvariantCulture) == 0)
160                                         enableSessionState = PagesEnableSessionState.False;
161                                 else
162                                         ThrowParseException ("Invalid value for enableSessionState: " + enabless);
163                         }
164
165                         string cp = GetString (atts, "CodePage", null);
166                         if (cp != null) {
167                                 if (responseEncoding != null)
168                                         ThrowParseException ("CodePage and ResponseEncoding are " +
169                                                 "mutually exclusive.");
170
171                                 int codepage = 0;
172                                 try {
173                                         codepage = (int) UInt32.Parse (cp);
174                                 } catch {
175                                         ThrowParseException ("Invalid value for CodePage: " + cp);
176                                 }
177
178                                 try {
179                                         Encoding.GetEncoding (codepage);
180                                 } catch {
181                                         ThrowParseException ("Unsupported codepage: " + cp);
182                                 }
183                         }
184                         
185                         responseEncoding = GetString (atts, "ResponseEncoding", null);
186                         if (responseEncoding != null) {
187                                 if (codepage != -1)
188                                         ThrowParseException ("CodePage and ResponseEncoding are " +
189                                                              "mutually exclusive.");
190
191                                 try {
192                                         Encoding.GetEncoding (responseEncoding);
193                                 } catch {
194                                         ThrowParseException ("Unsupported encoding: " + responseEncoding);
195                                 }
196                         }
197                         
198                         contentType = GetString (atts, "ContentType", null);
199
200                         string lcidStr = GetString (atts, "LCID", null);
201                         if (lcidStr != null) {
202                                 try {
203                                         lcid = (int) UInt32.Parse (lcidStr);
204                                 } catch {
205                                         ThrowParseException ("Invalid value for LCID: " + lcid);
206                                 }
207
208                                 CultureInfo ci = null;
209                                 try {
210                                         ci = new CultureInfo (lcid);
211                                 } catch {
212                                         ThrowParseException ("Unsupported LCID: " + lcid);
213                                 }
214
215                                 if (ci.IsNeutralCulture) {
216                                         string suggestedCulture = SuggestCulture (ci.Name);
217                                         string fmt = "LCID attribute must be set to a non-neutral Culture.";
218                                         if (suggestedCulture != null) {
219                                                 ThrowParseException (fmt + " Please try one of these: " +
220                                                                      suggestedCulture);
221                                         } else {
222                                                 ThrowParseException (fmt);
223                                         }
224                                 }
225                         }
226
227                         culture = GetString (atts, "Culture", null);
228                         if (culture != null) {
229                                 if (lcidStr != null) 
230                                         ThrowParseException ("Culture and LCID are mutually exclusive.");
231                                 
232                                 CultureInfo ci = null;
233                                 try {
234                                         if (!culture.StartsWith ("auto"))
235                                                 ci = new CultureInfo (culture);
236                                 } catch {
237                                         ThrowParseException ("Unsupported Culture: " + culture);
238                                 }
239
240                                 if (ci != null && ci.IsNeutralCulture) {
241                                         string suggestedCulture = SuggestCulture (culture);
242                                         string fmt = "Culture attribute must be set to a non-neutral Culture.";
243                                         if (suggestedCulture != null)
244                                                 ThrowParseException (fmt +
245                                                                 " Please try one of these: " + suggestedCulture);
246                                         else
247                                                 ThrowParseException (fmt);
248                                 }
249                         }
250
251                         uiculture = GetString (atts, "UICulture", null);
252                         if (uiculture != null) {
253                                 CultureInfo ci = null;
254                                 try {
255                                         if (!uiculture.StartsWith ("auto"))
256                                                 ci = new CultureInfo (uiculture);
257                                 } catch {
258                                         ThrowParseException ("Unsupported Culture: " + uiculture);
259                                 }
260
261                                 if (ci != null && ci.IsNeutralCulture) {
262                                         string suggestedCulture = SuggestCulture (uiculture);
263                                         string fmt = "UICulture attribute must be set to a non-neutral Culture.";
264                                         if (suggestedCulture != null)
265                                                 ThrowParseException (fmt +
266                                                                 " Please try one of these: " + suggestedCulture);
267                                         else
268                                                 ThrowParseException (fmt);
269                                 }
270                         }
271
272                         string tracestr = GetString (atts, "Trace", null);
273                         if (tracestr != null) {
274                                 haveTrace = true;
275                                 atts ["Trace"] = tracestr;
276                                 trace = GetBool (atts, "Trace", false);
277                         }
278
279                         string tracemodes = GetString (atts, "TraceMode", null);
280                         if (tracemodes != null) {
281                                 bool valid = true;
282                                 try {
283                                         tracemode = (TraceMode) Enum.Parse (typeof (TraceMode), tracemodes, false);
284                                 } catch {
285                                         valid = false;
286                                 }
287
288                                 if (!valid || tracemode == TraceMode.Default)
289                                         ThrowParseException ("The 'tracemode' attribute is case sensitive and must be " +
290                                                         "one of the following values: SortByTime, SortByCategory.");
291                         }
292
293                         errorPage = GetString (atts, "ErrorPage", null);
294                         validateRequest = GetBool (atts, "ValidateRequest", validateRequest);
295                         clientTarget = GetString (atts, "ClientTarget", null);
296                         if (clientTarget != null) {
297                                 clientTarget = clientTarget.Trim ();
298                                 ClientTargetSection sec = GetConfigSection <ClientTargetSection> ("system.web/clientTarget");
299                                 ClientTarget ct = null;
300                                 
301                                 if ((ct = sec.ClientTargets [clientTarget]) == null)
302                                         clientTarget = clientTarget.ToLowerInvariant ();
303                                 
304                                 if (ct == null && (ct = sec.ClientTargets [clientTarget]) == null) {
305                                         ThrowParseException (String.Format (
306                                                         "ClientTarget '{0}' is an invalid alias. See the " +
307                                                         "documentation for <clientTarget> config. section.",
308                                                         clientTarget));
309                                 }
310                                 clientTarget = ct.UserAgent;
311                         }
312
313                         notBuffer = !GetBool (atts, "Buffer", true);
314                         async = GetBool (atts, "Async", false);
315                         string asyncTimeoutVal = GetString (atts, "AsyncTimeout", null);
316                         if (asyncTimeoutVal != null) {
317                                 try {
318                                         asyncTimeout = Int32.Parse (asyncTimeoutVal);
319                                 } catch (Exception) {
320                                         ThrowParseException ("AsyncTimeout must be an integer value");
321                                 }
322                         }
323                         
324                         masterPage = GetString (atts, "MasterPageFile", masterPage);
325                         
326                         if (!String.IsNullOrEmpty (masterPage)) {
327                                 if (!HostingEnvironment.VirtualPathProvider.FileExists (masterPage))
328                                         ThrowParseFileNotFound (masterPage);
329                                 AddDependency (masterPage);
330                         }
331                         
332                         title = GetString(atts, "Title", null);
333
334                         theme = GetString (atts, "Theme", theme);
335                         styleSheetTheme = GetString (atts, "StyleSheetTheme", styleSheetTheme);
336                         enable_event_validation = GetBool (atts, "EnableEventValidation", enable_event_validation);
337                         maintainScrollPositionOnPostBack = GetBool (atts, "MaintainScrollPositionOnPostBack", maintainScrollPositionOnPostBack);
338
339                         if (atts.ContainsKey ("EnableViewState")) {
340                                 enableViewStateMac = GetBool (atts, "EnableViewStateMac", enableViewStateMac);
341                                 enableViewStateMacSet = true;
342                         }
343                         
344                         // Ignored by now
345                         GetString (atts, "SmartNavigation", null);
346
347                         base.ProcessMainAttributes (atts);
348                 }
349                 
350                 internal override void AddDirective (string directive, Hashtable atts)
351                 {
352                         bool isMasterType = String.Compare ("MasterType", directive, StringComparison.OrdinalIgnoreCase) == 0;
353                         bool isPreviousPageType = isMasterType ? false : String.Compare ("PreviousPageType", directive,
354                                                                                          StringComparison.OrdinalIgnoreCase) == 0;
355
356                         string typeName = null;
357                         string virtualPath = null;
358                         Type type = null;
359                         
360                         if (isMasterType || isPreviousPageType) {
361                                 PageParserFilter pfilter = PageParserFilter;
362                                 if (pfilter != null)
363                                         pfilter.PreprocessDirective (directive.ToLowerInvariant (), atts);
364                                 
365                                 typeName = GetString (atts, "TypeName", null);
366                                 virtualPath = GetString (atts, "VirtualPath", null);
367
368                                 if (typeName != null && virtualPath != null)
369                                         ThrowParseException (
370                                                 String.Format ("The '{0}' directive must have exactly one attribute: TypeName or VirtualPath", directive));
371                                 if (typeName != null) {
372                                         type = LoadType (typeName);
373                                         if (type == null)
374                                                 ThrowParseException (String.Format ("Could not load type '{0}'.", typeName));
375                                         if (isMasterType)
376                                                 masterType = type;
377                                         else
378                                                 previousPageType = type;
379                                 } else if (!String.IsNullOrEmpty (virtualPath)) {
380                                         if (!HostingEnvironment.VirtualPathProvider.FileExists (virtualPath))
381                                                 ThrowParseFileNotFound (virtualPath);
382
383                                         AddDependency (virtualPath);
384                                         if (isMasterType)
385                                                 masterVirtualPath = virtualPath;
386                                         else
387                                                 previousPageVirtualPath = virtualPath;
388                                 } else
389                                         ThrowParseException (String.Format ("The {0} directive must have either a TypeName or a VirtualPath attribute.", directive));
390
391                                 if (type != null)
392                                         AddAssembly (type.Assembly, true);
393                         } else
394                                 base.AddDirective (directive, atts);
395                 }
396                 
397                 static string SuggestCulture (string culture)
398                 {
399                         string retval = null;
400                         foreach (CultureInfo ci in CultureInfo.GetCultures (CultureTypes.SpecificCultures)) {
401                                 if (ci.Name.StartsWith (culture))
402                                         retval += ci.Name + " ";
403                         }
404                         return retval;
405                 }
406
407                 public static Type GetCompiledPageType (string virtualPath, string inputFile, HttpContext context)
408                 {
409                         return BuildManager.GetCompiledType (virtualPath);
410                 }
411                 
412                 protected override Type CompileIntoType ()
413                 {
414                         AspGenerator generator = new AspGenerator (this);
415                         return generator.GetCompiledType ();
416                 }
417
418                 internal bool EnableSessionState {
419                         get {
420                                 return enableSessionState == PagesEnableSessionState.True ||
421                                         ReadOnlySessionState;
422                         }
423                 }
424
425                 internal bool EnableViewStateMac {
426                         get { return enableViewStateMac; }
427                 }
428
429                 internal bool EnableViewStateMacSet {
430                         get { return enableViewStateMacSet; }
431                 }
432                 
433                 internal bool SmartNavigation {
434                         get { return smartNavigation; }
435                 }
436                 
437                 internal bool ReadOnlySessionState {
438                         get {
439                                 return enableSessionState == PagesEnableSessionState.ReadOnly;
440                         }
441                 }
442
443                 internal bool HaveTrace {
444                         get { return haveTrace; }
445                 }
446
447                 internal bool Trace {
448                         get { return trace; }
449                 }
450
451                 internal TraceMode TraceMode {
452                         get { return tracemode; }
453                 }               
454
455                 internal override string DefaultBaseTypeName {
456                         get { return PagesConfig.PageBaseType; }
457                 }
458                 
459                 internal override string DefaultDirectiveName {
460                         get { return "page"; }
461                 }
462
463                 internal string ResponseEncoding {
464                         get { return responseEncoding; }
465                 }
466
467                 internal string ContentType {
468                         get { return contentType; }
469                 }
470
471                 internal int CodePage {
472                         get { return codepage; }
473                 }
474
475                 internal string Culture {
476                         get { return culture; }
477                 }
478
479                 internal string UICulture {
480                         get { return uiculture; }
481                 }
482
483                 internal int LCID {
484                         get { return lcid; }
485                 }
486
487                 internal string ErrorPage {
488                         get { return errorPage; }
489                 }
490
491                 internal bool ValidateRequest {
492                         get { return validateRequest; }
493                 }
494
495                 internal string ClientTarget {
496                         get { return clientTarget; }
497                 }
498
499                 internal bool NotBuffer {
500                         get { return notBuffer; }
501                 }
502
503                 internal bool Async {
504                         get { return async; }
505                 }
506
507                 internal int AsyncTimeout {
508                         get { return asyncTimeout; }
509                 }
510                 
511                 internal string Theme {
512                         get { return theme; }
513                 }
514
515                 internal string StyleSheetTheme {
516                         get { return styleSheetTheme; }
517                 }
518
519                 internal string MasterPageFile {
520                         get { return masterPage; }
521                 }
522                 
523                 internal Type MasterType {
524                         get {
525                                 if (masterType == null && !String.IsNullOrEmpty (masterVirtualPath))
526                                         masterType = BuildManager.GetCompiledType (masterVirtualPath);
527                                 
528                                 return masterType;
529                         }
530                 }
531
532                 internal string Title {
533                         get { return title; }
534                 }
535
536                 internal bool EnableEventValidation {
537                         get { return enable_event_validation; }
538                 }
539
540                 internal bool MaintainScrollPositionOnPostBack {
541                         get { return maintainScrollPositionOnPostBack; }
542                 }
543
544                 internal int MaxPageStateFieldLength {
545                         get { return maxPageStateFieldLength; }
546                 }
547
548                 internal Type PreviousPageType {
549                         get {
550                                 if (previousPageType == null && !String.IsNullOrEmpty (previousPageVirtualPath)) {
551                                         string mappedPath = MapPath (previousPageVirtualPath);
552                                         previousPageType = GetCompiledPageType (previousPageVirtualPath, mappedPath, HttpContext.Current);
553                                 }
554                                 
555                                 return previousPageType;
556                         }
557                 }
558         }
559 }
560