X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Web%2FSystem.Web.UI%2FTemplateParser.cs;h=4e8f30e54dd822a1d18cfa7917858d5048f99a7f;hb=56919138c9eec1b3acb3c0502dfb203e81e4ec77;hp=8489a13eb248bafdc0d2f7587c357726c0351316;hpb=b723df471e1bd7c31c6b6bb6c89552f5ff6976c8;p=mono.git diff --git a/mcs/class/System.Web/System.Web.UI/TemplateParser.cs b/mcs/class/System.Web/System.Web.UI/TemplateParser.cs index 8489a13eb24..4e8f30e54dd 100644 --- a/mcs/class/System.Web/System.Web.UI/TemplateParser.cs +++ b/mcs/class/System.Web/System.Web.UI/TemplateParser.cs @@ -44,7 +44,18 @@ using System.Collections.Generic; #endif namespace System.Web.UI { - + internal class ServerSideScript + { + public readonly string Script; + public readonly ILocation Location; + + public ServerSideScript (string script, ILocation location) + { + Script = script; + Location = location; + } + } + // CAS [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] @@ -61,34 +72,43 @@ namespace System.Web.UI { ArrayList interfaces; ArrayList scripts; Type baseType; - bool baseTypeIsGlobal; + bool baseTypeIsGlobal = true; string className; RootBuilder rootBuilder; bool debug; string compilerOptions; string language; + bool implicitLanguage; bool strictOn = false; bool explicitOn = false; bool linePragmasOn = false; bool output_cache; int oc_duration; string oc_header, oc_custom, oc_param, oc_controls; +#if NET_2_0 + string oc_content_encodings; +#endif bool oc_shared; OutputCacheLocation oc_location; CultureInfo invariantCulture = CultureInfo.InvariantCulture; #if NET_2_0 string src; + bool srcIsLegacy; string partialClassName; string codeFileBaseClass; string metaResourceKey; Type codeFileBaseClassType; List unknownMainAttributes; #endif + ILocation directiveLocation; + Assembly srcAssembly; int appAssemblyIndex = -1; internal TemplateParser () { + LoadConfigDefaults (); + imports = new ArrayList (); #if NET_2_0 AddNamespaces (imports); @@ -110,8 +130,10 @@ namespace System.Web.UI { assemblies = new ArrayList (); #if NET_2_0 + CompilationSection compConfig = CompilationConfig; + bool addAssembliesInBin = false; - foreach (AssemblyInfo info in CompilationConfig.Assemblies) { + foreach (AssemblyInfo info in compConfig.Assemblies) { if (info.Assembly == "*") addAssembliesInBin = true; else @@ -124,13 +146,21 @@ namespace System.Web.UI { imports.Add (info.Namespace); } #else - foreach (string a in CompilationConfig.Assemblies) + CompilationConfiguration compConfig = CompilationConfig; + + foreach (string a in compConfig.Assemblies) AddAssemblyByName (a); - if (CompilationConfig.AssembliesInBin) + if (compConfig.AssembliesInBin) AddAssembliesInBin (); #endif - language = CompilationConfig.DefaultLanguage; + language = compConfig.DefaultLanguage; + implicitLanguage = true; + } + + internal virtual void LoadConfigDefaults () + { + debug = CompilationConfig.Debug; } internal void AddApplicationAssembly () @@ -173,15 +203,21 @@ namespace System.Web.UI { if (!File.Exists (realpath)) throw new ParseException (Location, "Could not find file \"" + realpath + "\"."); - string vpath = UrlUtils.Combine (BaseVirtualDir, src); + string vpath = VirtualPathUtility.Combine (BaseVirtualDir, src); + if (VirtualPathUtility.IsAbsolute (vpath)) + vpath = VirtualPathUtility.ToAppRelative (vpath); + Type type = null; - AddDependency (realpath); + AddDependency (vpath); try { - ArrayList other_deps = new ArrayList (); +#if NET_2_0 + type = BuildManager.GetCompiledType (vpath); +#else + ArrayList other_deps = new ArrayList (); type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context); - foreach (string s in other_deps) { + foreach (string s in other_deps) AddDependency (s); - } +#endif } catch (ParseException pe) { if (this is UserControlParser) throw new ParseException (Location, pe.Message, pe); @@ -195,8 +231,11 @@ namespace System.Web.UI { internal void RegisterNamespace (string tagPrefix, string ns, string assembly) { AddImport (ns); - Assembly ass = AddAssemblyByName (assembly); - AddDependency (ass.Location); + Assembly ass = null; + + if (assembly != null && assembly.Length > 0) + ass = AddAssemblyByName (assembly); + RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns); } @@ -285,65 +324,71 @@ namespace System.Web.UI { if (atts ["Duration"] == null) ThrowParseException ("The directive is missing a 'duration' attribute."); - if (atts ["VaryByParam"] == null) - ThrowParseException ("This directive is missing a 'VaryByParam' " + - "attribute, which should be set to \"none\", \"*\", " + + if (atts ["VaryByParam"] == null && atts ["VaryByControl"] == null) + ThrowParseException ("This directive is missing 'VaryByParam' " + + "or 'VaryByControl' attribute, which should be set to \"none\", \"*\", " + "or a list of name/value pairs."); foreach (DictionaryEntry entry in atts) { string key = (string) entry.Key; switch (key.ToLower ()) { - case "duration": - oc_duration = Int32.Parse ((string) entry.Value); - if (oc_duration < 1) - ThrowParseException ("The 'duration' attribute must be set " + - "to a positive integer value"); - break; - case "varybyparam": - oc_param = (string) entry.Value; - if (String.Compare (oc_param, "none") == 0) - oc_param = null; - break; - case "varybyheader": - oc_header = (string) entry.Value; - break; - case "varybycustom": - oc_custom = (string) entry.Value; - break; - case "location": - if (!(this is PageParser)) - goto default; - - try { - oc_location = (OutputCacheLocation) Enum.Parse ( - typeof (OutputCacheLocation), (string) entry.Value, true); - } catch { - ThrowParseException ("The 'location' attribute is case sensitive and " + - "must be one of the following values: Any, Client, " + - "Downstream, Server, None, ServerAndClient."); - } - break; - case "varybycontrol": - if (this is PageParser) - goto default; - - oc_controls = (string) entry.Value; - break; - case "shared": - if (this is PageParser) - goto default; - - try { - oc_shared = Boolean.Parse ((string) entry.Value); - } catch { - ThrowParseException ("The 'shared' attribute is case sensitive" + - " and must be set to 'true' or 'false'."); - } - break; - default: - ThrowParseException ("The '" + key + "' attribute is not " + - "supported by the 'Outputcache' directive."); - break; + case "duration": + oc_duration = Int32.Parse ((string) entry.Value); + if (oc_duration < 1) + ThrowParseException ("The 'duration' attribute must be set " + + "to a positive integer value"); + break; +#if NET_2_0 + case "varybycontentencodings": + oc_content_encodings = (string) entry.Value; + break; +#endif + case "varybyparam": + oc_param = (string) entry.Value; + if (String.Compare (oc_param, "none") == 0) + oc_param = null; + break; + case "varybyheader": + oc_header = (string) entry.Value; + break; + case "varybycustom": + oc_custom = (string) entry.Value; + break; + case "location": + if (!(this is PageParser)) + goto default; + + try { + oc_location = (OutputCacheLocation) Enum.Parse ( + typeof (OutputCacheLocation), (string) entry.Value, true); + } catch { + ThrowParseException ("The 'location' attribute is case sensitive and " + + "must be one of the following values: Any, Client, " + + "Downstream, Server, None, ServerAndClient."); + } + break; + case "varybycontrol": +#if ONLY_1_1 + if (this is PageParser) + goto default; +#endif + oc_controls = (string) entry.Value; + break; + case "shared": + if (this is PageParser) + goto default; + + try { + oc_shared = Boolean.Parse ((string) entry.Value); + } catch { + ThrowParseException ("The 'shared' attribute is case sensitive" + + " and must be set to 'true' or 'false'."); + } + break; + default: + ThrowParseException ("The '" + key + "' attribute is not " + + "supported by the 'Outputcache' directive."); + break; } } @@ -356,56 +401,33 @@ namespace System.Web.UI { internal Type LoadType (string typeName) { - // First try loaded assemblies, then try assemblies in Bin directory. - Type type = null; - bool seenBin = false; - Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies (); - foreach (Assembly ass in assemblies) { - type = ass.GetType (typeName); - if (type == null) - continue; - - if (Path.GetDirectoryName (ass.Location) != PrivateBinPath) { - AddAssembly (ass, true); - } else { - seenBin = true; + Type type = HttpApplication.LoadType (typeName); + if (type == null) + return null; + Assembly asm = type.Assembly; + string location = asm.Location; + + string dirname = Path.GetDirectoryName (location); + bool doAddAssembly = true; + foreach (string dir in HttpApplication.BinDirectories) { + if (dirname == dir) { + doAddAssembly = false; + break; } - - AddDependency (ass.Location); - return type; } - if (seenBin) - return null; - - // Load from bin - if (!Directory.Exists (PrivateBinPath)) - return null; - - string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll"); - foreach (string s in binDlls) { - Assembly binA = Assembly.LoadFrom (s); - type = binA.GetType (typeName); - if (type == null) - continue; - - AddDependency (binA.Location); - return type; - } + if (doAddAssembly) + AddAssembly (asm, true); - return null; + return type; } void AddAssembliesInBin () { - if (!Directory.Exists (PrivateBinPath)) - return; - - string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll"); - foreach (string s in binDlls) + foreach (string s in HttpApplication.BinDirectoryAssemblies) assemblies.Add (s); } - + internal virtual void AddInterface (string iface) { if (interfaces == null) @@ -426,9 +448,8 @@ namespace System.Web.UI { internal virtual void AddSourceDependency (string filename) { - if (dependencies != null && dependencies.Contains (filename)) { + if (dependencies != null && dependencies.Contains (filename)) ThrowParseException ("Circular file references are not allowed. File: " + filename); - } AddDependency (filename); } @@ -502,11 +523,9 @@ namespace System.Web.UI { Assembly assembly = null; Exception error = null; - if (name.IndexOf (',') != -1) { - try { - assembly = Assembly.Load (name); - } catch (Exception e) { error = e; } - } + try { + assembly = Assembly.Load (name); + } catch (Exception e) { error = e; } if (assembly == null) { try { @@ -523,25 +542,37 @@ namespace System.Web.UI { internal virtual void ProcessMainAttributes (Hashtable atts) { + directiveLocation = new System.Web.Compilation.Location (Location); + +#if NET_2_0 + CompilationSection compConfig; +#else + CompilationConfiguration compConfig; +#endif + + compConfig = CompilationConfig; + atts.Remove ("Description"); // ignored #if NET_1_1 atts.Remove ("CodeBehind"); // ignored #endif atts.Remove ("AspCompat"); // ignored -#if NET_2_0 - // these two are ignored for the moment - atts.Remove ("Async"); - atts.Remove ("AsyncTimeOut"); -#endif - debug = GetBool (atts, "Debug", true); + debug = GetBool (atts, "Debug", compConfig.Debug); compilerOptions = GetString (atts, "CompilerOptions", ""); - language = GetString (atts, "Language", CompilationConfig.DefaultLanguage); - strictOn = GetBool (atts, "Strict", CompilationConfig.Strict); - explicitOn = GetBool (atts, "Explicit", CompilationConfig.Explicit); + language = GetString (atts, "Language", ""); + if (language.Length != 0) + implicitLanguage = false; + else + language = compConfig.DefaultLanguage; + + strictOn = GetBool (atts, "Strict", compConfig.Strict); + explicitOn = GetBool (atts, "Explicit", compConfig.Explicit); linePragmasOn = GetBool (atts, "LinePragmas", false); string inherits = GetString (atts, "Inherits", null); + string srcRealPath = null; + #if NET_2_0 // In ASP 2, the source file is actually integrated with // the generated file via the use of partial classes. This @@ -552,12 +583,31 @@ namespace System.Web.UI { if (src == null && codeFileBaseClass != null) ThrowParseException ("The 'CodeFileBaseClass' attribute cannot be used without a 'CodeFile' attribute"); + + string legacySrc = GetString (atts, "Src", null); + if (legacySrc != null) { + legacySrc = UrlUtils.Combine (BaseVirtualDir, legacySrc); + if (src == null) { + src = legacySrc; + legacySrc = MapPath (legacySrc, false); + srcRealPath = legacySrc; + if (!File.Exists (srcRealPath)) + ThrowParseException ("File " + src + " not found"); + + srcIsLegacy = true; + } else + legacySrc = MapPath (legacySrc, false); + + GetAssemblyFromSource (legacySrc); + AddDependency (legacySrc); + } - if (src != null && inherits != null) { + if (!srcIsLegacy && src != null && inherits != null) { // Make sure the source exists src = UrlUtils.Combine (BaseVirtualDir, src); - string realPath = MapPath (src, false); - if (!File.Exists (realPath)) + srcRealPath = MapPath (src, false); + + if (!File.Exists (srcRealPath)) ThrowParseException ("File " + src + " not found"); // We are going to create a partial class that shares @@ -569,7 +619,7 @@ namespace System.Web.UI { // Add the code file as an option to the // compiler. This lets both files be compiled at once. - compilerOptions += " \"" + realPath + "\""; + compilerOptions += " \"" + srcRealPath + "\""; if (codeFileBaseClass != null) { try { @@ -588,15 +638,34 @@ namespace System.Web.UI { #else string src = GetString (atts, "Src", null); - if (src != null) + if (src != null) { + srcRealPath = MapPath (src, false); srcAssembly = GetAssemblyFromSource (src); - + } + if (inherits != null) SetBaseType (inherits); #endif + if (src != null) { + if (VirtualPathUtility.IsAbsolute (src)) + src = VirtualPathUtility.ToAppRelative (src); + AddDependency (src); + } + className = GetString (atts, "ClassName", null); - if (className != null && !CodeGenerator.IsValidLanguageIndependentIdentifier (className)) - ThrowParseException (String.Format ("'{0}' is not valid for 'className'", className)); + if (className != null) { +#if NET_2_0 + string [] identifiers = className.Split ('.'); + for (int i = 0; i < identifiers.Length; i++) + if (!CodeGenerator.IsValidLanguageIndependentIdentifier (identifiers [i])) + ThrowParseException (String.Format ("'{0}' is not a valid " + + "value for attribute 'classname'.", className)); +#else + if (!CodeGenerator.IsValidLanguageIndependentIdentifier (className)) + ThrowParseException (String.Format ("'{0}' is not a valid " + + "value for attribute 'classname'.", className)); +#endif + } #if NET_2_0 if (this is TemplateControlParser) @@ -698,9 +767,11 @@ namespace System.Web.UI { internal void SetBaseType (string type) { - if (type == DefaultBaseTypeName) + if (type == null || type == DefaultBaseTypeName) { + baseType = DefaultBaseType; return; - + } + Type parent = null; if (srcAssembly != null) parent = srcAssembly.GetType (type); @@ -715,10 +786,14 @@ namespace System.Web.UI { ThrowParseException ("The parent type does not derive from " + DefaultBaseType); baseType = parent; - if (parent.FullName.IndexOf ('.') == -1) - baseTypeIsGlobal = true; } + internal void SetLanguage (string language) + { + this.language = language; + implicitLanguage = false; + } + Assembly GetAssemblyFromSource (string vpath) { vpath = UrlUtils.Combine (BaseVirtualDir, vpath); @@ -726,9 +801,9 @@ namespace System.Web.UI { if (!File.Exists (realPath)) ThrowParseException ("File " + vpath + " not found"); - AddSourceDependency (realPath); + AddSourceDependency (vpath); - CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies); + CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies, Debug); if (result.NativeCompilerReturnValue != 0) { StreamReader reader = new StreamReader (realPath); throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ()); @@ -736,12 +811,23 @@ namespace System.Web.UI { AddAssembly (result.CompiledAssembly, true); return result.CompiledAssembly; - } - - internal abstract Type DefaultBaseType { get; } + } + internal abstract string DefaultBaseTypeName { get; } internal abstract string DefaultDirectiveName { get; } + internal Type DefaultBaseType { + get { + Type type = Type.GetType (DefaultBaseTypeName, true); + + return type; + } + } + + internal ILocation DirectiveLocation { + get { return directiveLocation; } + } + internal string InputFile { get { return inputFile; } @@ -750,9 +836,13 @@ namespace System.Web.UI { #if NET_2_0 internal bool IsPartial { - get { return src != null; } + get { return (!srcIsLegacy && src != null); } } + internal string CodeBehindSource { + get { return src; } + } + internal string PartialClassName { get { return partialClassName; } } @@ -776,24 +866,23 @@ namespace System.Web.UI { } #endif - internal string Text - { + internal string Text { get { return text; } set { text = value; } } - internal Type BaseType - { + internal Type BaseType { get { if (baseType == null) - baseType = DefaultBaseType; - + SetBaseType (DefaultBaseTypeName); + return baseType; } } internal bool BaseTypeIsGlobal { get { return baseTypeIsGlobal; } + set { baseTypeIsGlobal = value; } } internal string ClassName { @@ -803,8 +892,24 @@ namespace System.Web.UI { #if NET_2_0 string physPath = HttpContext.Current.Request.PhysicalApplicationPath; + string inFile; + + if (String.IsNullOrEmpty (inputFile)) { + inFile = null; + StreamReader sr = Reader as StreamReader; + + if (sr != null) { + FileStream fr = sr.BaseStream as FileStream; + if (fr != null) + inFile = fr.Name; + } + } else + inFile = inputFile; + + if (String.IsNullOrEmpty (inFile)) + throw new HttpException ("Unable to determine class name - no input file found."); - if (StrUtils.StartsWith (inputFile, physPath)) { + if (StrUtils.StartsWith (inFile, physPath)) { className = inputFile.Substring (physPath.Length).ToLower (CultureInfo.InvariantCulture); className = className.Replace ('.', '_'); className = className.Replace ('/', '_').Replace ('\\', '_'); @@ -822,18 +927,6 @@ namespace System.Web.UI { } } - internal string PrivateBinPath { - get { - if (privateBinPath != null) - return privateBinPath; - - AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation; - privateBinPath = Path.Combine (setup.ApplicationBase, setup.PrivateBinPath); - - return privateBinPath; - } - } - internal ArrayList Scripts { get { if (scripts == null) @@ -882,6 +975,10 @@ namespace System.Web.UI { get { return language; } } + internal bool ImplicitLanguage { + get { return implicitLanguage; } + } + internal bool StrictOn { get { return strictOn; } } @@ -902,6 +999,17 @@ namespace System.Web.UI { get { return oc_duration; } } +#if NET_2_0 + internal string OutputCacheVaryByContentEncodings { + get { return oc_content_encodings; } + } + + internal virtual TextReader Reader { + get { return null; } + set { /* no-op */ } + } +#endif + internal string OutputCacheVaryByHeader { get { return oc_header; } }