// Authors:
// Duncan Mak (duncan@ximian.com)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Marek Habersack (mhabersack@novell.com)
//
// (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System.CodeDom.Compiler;
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Security.Permissions;
+using System.Text;
+using System.Threading;
using System.Web.Compilation;
using System.Web.Configuration;
+using System.Web.Hosting;
using System.Web.Util;
-#if NET_2_0
-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)]
public abstract class TemplateParser : BaseParser
{
+ [Flags]
+ internal enum OutputCacheParsedParams
+ {
+ Location = 0x0001,
+ CacheProfile = 0x0002,
+ NoStore = 0x0004,
+ SqlDependency = 0x0008,
+ VaryByCustom = 0x0010,
+ VaryByHeader = 0x0020,
+ VaryByControl = 0x0040,
+ VaryByContentEncodings = 0x0080
+ }
+
string inputFile;
string text;
- string privateBinPath;
Hashtable mainAttributes;
ArrayList dependencies;
ArrayList assemblies;
Hashtable anames;
- ArrayList imports;
- ArrayList interfaces;
- ArrayList scripts;
+ string[] binDirAssemblies;
+ Dictionary <string, bool> namespacesCache;
+ Dictionary <string, bool> imports;
+ List <string> interfaces;
+ List <ServerSideScript> 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 strictOn ;
+ bool explicitOn;
+ bool linePragmasOn = true;
bool output_cache;
int oc_duration;
string oc_header, oc_custom, oc_param, oc_controls;
+ string oc_content_encodings, oc_cacheprofile, oc_sqldependency;
+ bool oc_nostore;
+ OutputCacheParsedParams oc_parsed_params = 0;
bool oc_shared;
OutputCacheLocation oc_location;
- CultureInfo invariantCulture = CultureInfo.InvariantCulture;
-#if NET_2_0
+
+ // Kludge needed to support pre-parsing of the main directive (see
+ // AspNetGenerator.GetRootBuilderType)
+ internal int allowedMainDirectives = 0;
+
+ byte[] md5checksum;
string src;
+ bool srcIsLegacy;
string partialClassName;
string codeFileBaseClass;
string metaResourceKey;
Type codeFileBaseClassType;
+ Type pageParserFilterType;
+ PageParserFilter pageParserFilter;
+
List <UnknownAttributeDescriptor> unknownMainAttributes;
-#endif
- Assembly srcAssembly;
+ Stack <string> includeDirs;
+ List <string> registeredTagNames;
+ ILocation directiveLocation;
+
int appAssemblyIndex = -1;
internal TemplateParser ()
{
- imports = new ArrayList ();
-#if NET_2_0
- AddNamespaces (imports);
-#else
- imports.Add ("System");
- imports.Add ("System.Collections");
- imports.Add ("System.Collections.Specialized");
- imports.Add ("System.Configuration");
- imports.Add ("System.Text");
- imports.Add ("System.Text.RegularExpressions");
- imports.Add ("System.Web");
- imports.Add ("System.Web.Caching");
- imports.Add ("System.Web.Security");
- imports.Add ("System.Web.SessionState");
- imports.Add ("System.Web.UI");
- imports.Add ("System.Web.UI.WebControls");
- imports.Add ("System.Web.UI.HtmlControls");
-#endif
-
+ imports = new Dictionary <string, bool> (StringComparer.Ordinal);
+ LoadConfigDefaults ();
assemblies = new ArrayList ();
-#if NET_2_0
- bool addAssembliesInBin = false;
- foreach (AssemblyInfo info in CompilationConfig.Assemblies) {
- if (info.Assembly == "*")
- addAssembliesInBin = true;
- else
+ CompilationSection compConfig = CompilationConfig;
+ foreach (AssemblyInfo info in compConfig.Assemblies) {
+ if (info.Assembly != "*")
AddAssemblyByName (info.Assembly);
}
- if (addAssembliesInBin)
- AddAssembliesInBin ();
- foreach (NamespaceInfo info in PagesConfig.Namespaces) {
- imports.Add (info.Namespace);
- }
-#else
- foreach (string a in CompilationConfig.Assemblies)
- AddAssemblyByName (a);
- if (CompilationConfig.AssembliesInBin)
- AddAssembliesInBin ();
-#endif
-
- language = CompilationConfig.DefaultLanguage;
+ language = compConfig.DefaultLanguage;
implicitLanguage = true;
}
+
+ internal virtual void LoadConfigDefaults ()
+ {
+ AddNamespaces (imports);
+ debug = CompilationConfig.Debug;
+ }
internal void AddApplicationAssembly ()
{
protected abstract Type CompileIntoType ();
-#if NET_2_0
- void AddNamespaces (ArrayList imports)
+ internal void AddControl (Type type, IDictionary attributes)
+ {
+ AspGenerator generator = AspGenerator;
+ if (generator == null)
+ return;
+ generator.AddControl (type, attributes);
+ }
+
+ void AddNamespaces (Dictionary <string, bool> imports)
{
if (BuildManager.HaveResources)
- imports.Add ("System.Resources");
+ imports.Add ("System.Resources", true);
- PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
+ PagesSection pages = PagesConfig;
if (pages == null)
return;
NamespaceCollection namespaces = pages.Namespaces;
if (namespaces == null || namespaces.Count == 0)
return;
-
- foreach (NamespaceInfo nsi in namespaces)
- imports.Add (nsi.Namespace);
+
+ foreach (NamespaceInfo nsi in namespaces) {
+ string ns = nsi.Namespace;
+ if (imports.ContainsKey (ns))
+ continue;
+
+ imports.Add (ns, true);
+ }
}
-#endif
internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
{
- string realpath = MapPath (src);
- if (String.Compare (realpath, inputFile, false, invariantCulture) == 0)
+ string realpath = null;
+ bool fileExists = false;
+ VirtualFile vf = null;
+ VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
+ VirtualPath vp = new VirtualPath (src, BaseVirtualDir);
+ string vpAbsolute = vp.Absolute;
+
+ if (vpp.FileExists (vpAbsolute)) {
+ fileExists = true;
+ vf = vpp.GetFile (vpAbsolute);
+ if (vf != null)
+ realpath = MapPath (vf.VirtualPath);
+ }
+
+ if (!fileExists)
+ ThrowParseFileNotFound (src);
+
+ if (String.Compare (realpath, inputFile, false, Helpers.InvariantCulture) == 0)
return;
+
+ string vpath = vf.VirtualPath;
- if (!File.Exists (realpath))
- throw new ParseException (Location, "Could not find file \"" + realpath + "\".");
- string vpath = UrlUtils.Combine (BaseVirtualDir, src);
- Type type = null;
- AddDependency (realpath);
try {
- ArrayList other_deps = new ArrayList ();
- type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
- foreach (string s in other_deps) {
- AddDependency (s);
- }
+ RegisterTagName (tagPrefix + ":" + tagName);
+ RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, vpath);
+ AddDependency (vpath);
} catch (ParseException pe) {
if (this is UserControlParser)
throw new ParseException (Location, pe.Message, pe);
throw;
}
-
- AddAssembly (type.Assembly, true);
- RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
}
internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
AddImport (ns);
Assembly ass = null;
- if (assembly != null && assembly.Length > 0) {
+ if (assembly != null && assembly.Length > 0)
ass = AddAssemblyByName (assembly);
- AddDependency (ass.Location);
- }
RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
}
internal virtual void AddDirective (string directive, Hashtable atts)
{
- if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
- if (mainAttributes != null)
+ var pageParserFilter = PageParserFilter;
+ if (String.Compare (directive, DefaultDirectiveName, true, Helpers.InvariantCulture) == 0) {
+ bool allowMainDirective = allowedMainDirectives > 0;
+
+ if (mainAttributes != null && !allowMainDirective)
ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
+ allowedMainDirectives--;
+ if (mainAttributes != null)
+ return;
+
+ if (pageParserFilter != null)
+ pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
+
mainAttributes = atts;
ProcessMainAttributes (mainAttributes);
return;
- }
-
- int cmp = String.Compare ("Assembly", directive, true);
+ } else if (pageParserFilter != null)
+ pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
+
+ int cmp = String.Compare ("Assembly", directive, true, Helpers.InvariantCulture);
if (cmp == 0) {
string name = GetString (atts, "Name", null);
string src = GetString (atts, "Src", null);
return;
}
- cmp = String.Compare ("Import", directive, true);
+ cmp = String.Compare ("Import", directive, true, Helpers.InvariantCulture);
if (cmp == 0) {
string namesp = GetString (atts, "Namespace", null);
if (atts.Count > 0)
ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
- if (namesp != null && namesp != "")
- AddImport (namesp);
+ AddImport (namesp);
return;
}
- cmp = String.Compare ("Implements", directive, true);
+ cmp = String.Compare ("Implements", directive, true, Helpers.InvariantCulture);
if (cmp == 0) {
string ifacename = GetString (atts, "Interface", "");
return;
}
- cmp = String.Compare ("OutputCache", directive, true);
+ cmp = String.Compare ("OutputCache", directive, true, Helpers.InvariantCulture);
if (cmp == 0) {
HttpResponse response = HttpContext.Current.Response;
if (response != null)
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;
+ if (key == null)
+ continue;
+
+ switch (key.ToLower (Helpers.InvariantCulture)) {
+ 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;
- 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 "sqldependency":
+ oc_sqldependency = (string) entry.Value;
+ break;
+
+ case "nostore":
+ try {
+ oc_nostore = Boolean.Parse ((string) entry.Value);
+ oc_parsed_params |= OutputCacheParsedParams.NoStore;
+ } catch {
+ ThrowParseException ("The 'NoStore' attribute is case sensitive" +
+ " and must be set to 'true' or 'false'.");
+ }
+ break;
+
+ case "cacheprofile":
+ oc_cacheprofile = (string) entry.Value;
+ oc_parsed_params |= OutputCacheParsedParams.CacheProfile;
+ break;
+
+ case "varybycontentencodings":
+ oc_content_encodings = (string) entry.Value;
+ oc_parsed_params |= OutputCacheParsedParams.VaryByContentEncodings;
+ break;
+
+ case "varybyparam":
+ oc_param = (string) entry.Value;
+ if (String.Compare (oc_param, "none", true, Helpers.InvariantCulture) == 0)
+ oc_param = null;
+ break;
+ case "varybyheader":
+ oc_header = (string) entry.Value;
+ oc_parsed_params |= OutputCacheParsedParams.VaryByHeader;
+ break;
+ case "varybycustom":
+ oc_custom = (string) entry.Value;
+ oc_parsed_params |= OutputCacheParsedParams.VaryByCustom;
+ break;
+ case "location":
+ if (!(this is PageParser))
+ goto default;
+
+ try {
+ oc_location = (OutputCacheLocation) Enum.Parse (
+ typeof (OutputCacheLocation), (string) entry.Value, true);
+ oc_parsed_params |= OutputCacheParsedParams.Location;
+ } 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":
+ oc_controls = (string) entry.Value;
+ oc_parsed_params |= OutputCacheParsedParams.VaryByControl;
+ 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;
}
}
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;
- }
-
- AddDependency (ass.Location);
- return type;
- }
-
- if (seenBin)
+ 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;
+ if (dirname == HttpApplication.BinDirectory)
+ doAddAssembly = false;
- // 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)
- assemblies.Add (s);
- }
-
internal virtual void AddInterface (string iface)
{
if (interfaces == null)
- interfaces = new ArrayList ();
+ interfaces = new List <string> ();
if (!interfaces.Contains (iface))
interfaces.Add (iface);
internal virtual void AddImport (string namesp)
{
+ if (namesp == null || namesp.Length == 0)
+ return;
+
if (imports == null)
- imports = new ArrayList ();
+ imports = new Dictionary <string, bool> (StringComparer.Ordinal);
+
+ if (imports.ContainsKey (namesp))
+ return;
+
+ imports.Add (namesp, true);
+ AddAssemblyForNamespace (namesp);
+ }
- if (!imports.Contains (namesp))
- imports.Add (namesp);
+ void AddAssemblyForNamespace (string namesp)
+ {
+ if (binDirAssemblies == null)
+ binDirAssemblies = HttpApplication.BinDirectoryAssemblies;
+ if (binDirAssemblies.Length == 0)
+ return;
+
+ if (namespacesCache == null)
+ namespacesCache = new Dictionary <string, bool> ();
+ else if (namespacesCache.ContainsKey (namesp))
+ return;
+
+ foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
+ if (FindNamespaceInAssembly (asm, namesp))
+ return;
+
+ IList tla = BuildManager.TopLevelAssemblies;
+ if (tla != null && tla.Count > 0) {
+ foreach (Assembly asm in tla) {
+ if (FindNamespaceInAssembly (asm, namesp))
+ return;
+ }
+ }
+
+ Assembly a;
+ foreach (string s in binDirAssemblies) {
+ a = Assembly.LoadFrom (s);
+ if (FindNamespaceInAssembly (a, namesp))
+ return;
+ }
}
+ bool FindNamespaceInAssembly (Assembly asm, string namesp)
+ {
+ Type[] asmTypes;
+
+ try {
+ asmTypes = asm.GetTypes ();
+ } catch (ReflectionTypeLoadException) {
+ // ignore
+ return false;
+ }
+
+ foreach (Type type in asmTypes) {
+ if (String.Compare (type.Namespace, namesp, StringComparison.Ordinal) == 0) {
+ namespacesCache.Add (namesp, true);
+ AddAssembly (asm, true);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
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);
}
internal virtual void AddDependency (string filename)
{
- if (filename == "")
+ if (filename == null || filename == String.Empty)
return;
if (dependencies == null)
internal virtual void AddAssembly (Assembly assembly, bool fullPath)
{
- if (assembly.Location == "")
+ if (assembly == null || assembly.Location == String.Empty)
return;
if (anames == null)
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 {
internal virtual void ProcessMainAttributes (Hashtable atts)
{
+ directiveLocation = new System.Web.Compilation.Location (Location);
+ CompilationSection compConfig;
+
+ 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", "");
if (language.Length != 0)
implicitLanguage = false;
else
- language = CompilationConfig.DefaultLanguage;
-
- strictOn = GetBool (atts, "Strict", CompilationConfig.Strict);
- explicitOn = GetBool (atts, "Explicit", CompilationConfig.Explicit);
- linePragmasOn = GetBool (atts, "LinePragmas", false);
+ language = compConfig.DefaultLanguage;
+ strictOn = GetBool (atts, "Strict", compConfig.Strict);
+ explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
+ if (atts.ContainsKey ("LinePragmas"))
+ linePragmasOn = GetBool (atts, "LinePragmas", true);
+
string inherits = GetString (atts, "Inherits", null);
-#if NET_2_0
+ string srcRealPath = null;
+
// In ASP 2, the source file is actually integrated with
// the generated file via the use of partial classes. This
// means that the code file has to be confirmed, but not
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);
+ GetAssemblyFromSource (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);
+
+ 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 (!HostingEnvironment.VirtualPathProvider.FileExists (src))
ThrowParseException ("File " + src + " not found");
// We are going to create a partial class that shares
// 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 {
// Single-Page model.
SetBaseType (inherits);
}
-#else
- string src = GetString (atts, "Src", null);
-
- if (src != null)
- 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) {
-#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)
metaResourceKey = GetString (atts, "meta:resourcekey", null);
}
return;
}
-#endif
+
if (atts.Count > 0)
ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
}
-#if NET_2_0
+ void RegisterTagName (string tagName)
+ {
+ if (registeredTagNames == null)
+ registeredTagNames = new List <string> ();
+
+ if (registeredTagNames.Contains (tagName))
+ return;
+
+ registeredTagNames.Add (tagName);
+ }
+
void CheckUnknownAttribute (string name, string val, string inherits)
{
MemberInfo mi = null;
bool missing = false;
- string memberName = name.Trim ().ToLower (CultureInfo.InvariantCulture);
+ string memberName = name.Trim ().ToLower (Helpers.InvariantCulture);
Type parent = codeFileBaseClassType;
if (parent == null)
UnknownAttributeDescriptor desc = new UnknownAttributeDescriptor (mi, value);
unknownMainAttributes.Add (desc);
}
-#endif
internal void SetBaseType (string type)
{
- if (type == DefaultBaseTypeName)
- return;
-
- Type parent = null;
- if (srcAssembly != null)
- parent = srcAssembly.GetType (type);
+ Type parent;
+ if (type == null || type == DefaultBaseTypeName)
+ parent = DefaultBaseType;
+ else
+ parent = null;
- if (parent == null)
+ if (parent == null) {
parent = LoadType (type);
- if (parent == null)
- ThrowParseException ("Cannot find type " + type);
+ if (parent == null)
+ ThrowParseException ("Cannot find type " + type);
- if (!DefaultBaseType.IsAssignableFrom (parent))
- ThrowParseException ("The parent type does not derive from " + DefaultBaseType);
+ if (!DefaultBaseType.IsAssignableFrom (parent))
+ ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
+ }
+ var pageParserFilter = PageParserFilter;
+ if (pageParserFilter != null && !pageParserFilter.AllowBaseType (parent))
+ throw new HttpException ("Base type '" + parent + "' is not allowed.");
+
baseType = parent;
- if (parent.FullName.IndexOf ('.') == -1)
- baseTypeIsGlobal = true;
}
internal void SetLanguage (string language)
this.language = language;
implicitLanguage = false;
}
+
+ internal void PushIncludeDir (string dir)
+ {
+ if (includeDirs == null)
+ includeDirs = new Stack <string> (1);
+
+ includeDirs.Push (dir);
+ }
+
+ internal string PopIncludeDir ()
+ {
+ if (includeDirs == null || includeDirs.Count == 0)
+ return null;
+
+ return includeDirs.Pop () as string;
+ }
Assembly GetAssemblyFromSource (string vpath)
- {
+ {
vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
string realPath = MapPath (vpath, false);
if (!File.Exists (realPath))
ThrowParseException ("File " + vpath + " not found");
- AddSourceDependency (realPath);
+ AddSourceDependency (vpath);
+
+ CompilerResults result;
+ string tmp;
+ CompilerParameters parameters;
+ CodeDomProvider provider = BaseCompiler.CreateProvider (HttpContext.Current, language, out parameters, out tmp);
+ if (provider == null)
+ throw new HttpException ("Cannot find provider for language '" + language + "'.");
+
+ AssemblyBuilder abuilder = new AssemblyBuilder (provider);
+ abuilder.CompilerOptions = parameters;
+ abuilder.AddAssemblyReference (BuildManager.GetReferencedAssemblies () as List <Assembly>);
+ abuilder.AddCodeFile (realPath);
+ result = abuilder.BuildAssembly (new VirtualPath (vpath));
- CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies);
if (result.NativeCompilerReturnValue != 0) {
- StreamReader reader = new StreamReader (realPath);
- throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
+ using (StreamReader reader = new StreamReader (realPath)) {
+ throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
+ }
}
AddAssembly (result.CompiledAssembly, true);
return result.CompiledAssembly;
- }
-
- internal abstract Type DefaultBaseType { get; }
+ }
+
internal abstract string DefaultBaseTypeName { get; }
internal abstract string DefaultDirectiveName { get; }
+ internal bool LinePragmasOn {
+ get { return linePragmasOn; }
+ }
+
+ internal byte[] MD5Checksum {
+ get { return md5checksum; }
+ set { md5checksum = value; }
+ }
+
+ internal PageParserFilter PageParserFilter {
+ get {
+ if (pageParserFilter != null)
+ return pageParserFilter;
+
+ Type t = PageParserFilterType;
+ if (t == null)
+ return null;
+
+ pageParserFilter = Activator.CreateInstance (t) as PageParserFilter;
+ pageParserFilter.Initialize (this);
+
+ return pageParserFilter;
+ }
+ }
+
+ internal Type PageParserFilterType {
+ get {
+ if (pageParserFilterType == null) {
+ string typeName = PagesConfig.PageParserFilterType;
+ if (String.IsNullOrEmpty (typeName))
+ return null;
+
+ pageParserFilterType = HttpApplication.LoadType (typeName, true);
+ }
+
+ return pageParserFilterType;
+ }
+ }
+
+ internal Type DefaultBaseType {
+ get {
+ Type type = Type.GetType (DefaultBaseTypeName, true);
+
+ return type;
+ }
+ }
+
+ internal ILocation DirectiveLocation {
+ get { return directiveLocation; }
+ }
+
+ internal string ParserDir {
+ get {
+ if (includeDirs == null || includeDirs.Count == 0)
+ return BaseDir;
+
+ return includeDirs.Peek () as string;
+ }
+ }
+
internal string InputFile
{
get { return inputFile; }
set { inputFile = value; }
}
-#if NET_2_0
internal bool IsPartial {
- get { return src != null; }
+ get { return (!srcIsLegacy && src != null); }
}
+ internal string CodeBehindSource {
+ get {
+ if (srcIsLegacy)
+ return null;
+
+ return src;
+ }
+ }
+
internal string PartialClassName {
get { return partialClassName; }
}
{
get { return unknownMainAttributes; }
}
-#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; }
+ }
+
+ static long autoClassCounter = 0;
+
+ internal string EncodeIdentifier (string value)
+ {
+ if (value == null || value.Length == 0 || CodeGenerator.IsValidLanguageIndependentIdentifier (value))
+ return value;
+
+ StringBuilder ret = new StringBuilder ();
+
+ char ch = value [0];
+ switch (Char.GetUnicodeCategory (ch)) {
+ case UnicodeCategory.LetterNumber:
+ case UnicodeCategory.LowercaseLetter:
+ case UnicodeCategory.TitlecaseLetter:
+ case UnicodeCategory.UppercaseLetter:
+ case UnicodeCategory.OtherLetter:
+ case UnicodeCategory.ModifierLetter:
+ case UnicodeCategory.ConnectorPunctuation:
+ ret.Append (ch);
+ break;
+
+ case UnicodeCategory.DecimalDigitNumber:
+ ret.Append ('_');
+ ret.Append (ch);
+ break;
+
+ default:
+ ret.Append ('_');
+ break;
+ }
+
+ for (int i = 1; i < value.Length; i++) {
+ ch = value [i];
+ switch (Char.GetUnicodeCategory (ch)) {
+ case UnicodeCategory.LetterNumber:
+ case UnicodeCategory.LowercaseLetter:
+ case UnicodeCategory.TitlecaseLetter:
+ case UnicodeCategory.UppercaseLetter:
+ case UnicodeCategory.OtherLetter:
+ case UnicodeCategory.ModifierLetter:
+ case UnicodeCategory.ConnectorPunctuation:
+ case UnicodeCategory.DecimalDigitNumber:
+ case UnicodeCategory.NonSpacingMark:
+ case UnicodeCategory.SpacingCombiningMark:
+ case UnicodeCategory.Format:
+ ret.Append (ch);
+ break;
+
+ default:
+ ret.Append ('_');
+ break;
+ }
+ }
+
+ return ret.ToString ();
}
internal string ClassName {
if (className != null)
return className;
-#if NET_2_0
string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
+ string inFile;
- if (StrUtils.StartsWith (inputFile, physPath)) {
- className = inputFile.Substring (physPath.Length).ToLower (CultureInfo.InvariantCulture);
- className = className.Replace ('.', '_');
- className = className.Replace ('/', '_').Replace ('\\', '_');
+ if (String.IsNullOrEmpty (inputFile)) {
+ inFile = null;
+ using (StreamReader sr = Reader as StreamReader) {
+ if (sr != null) {
+ FileStream fr = sr.BaseStream as FileStream;
+ if (fr != null)
+ inFile = fr.Name;
+ }
+ }
} else
-#endif
- className = Path.GetFileName (inputFile).Replace ('.', '_');
- className = className.Replace ('-', '_');
- className = className.Replace (' ', '_');
+ inFile = inputFile;
- if (Char.IsDigit(className[0])) {
- className = "_" + className;
+ if (String.IsNullOrEmpty (inFile)) {
+ // generate a unique class name
+ long suffix;
+ suffix = Interlocked.Increment (ref autoClassCounter);
+ className = String.Format ("autoclass_nosource_{0:x}", suffix);
+ return className;
}
-
+
+ if (StrUtils.StartsWith (inFile, physPath))
+ className = inputFile.Substring (physPath.Length).ToLower (Helpers.InvariantCulture);
+ else
+ className = Path.GetFileName (inputFile);
+ className = EncodeIdentifier (className);
return className;
}
}
- 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 {
+ internal List <ServerSideScript> Scripts {
get {
if (scripts == null)
- scripts = new ArrayList ();
+ scripts = new List <ServerSideScript> ();
return scripts;
}
}
- internal ArrayList Imports {
+ internal Dictionary <string, bool> Imports {
get { return imports; }
}
+ internal List <string> Interfaces {
+ get { return interfaces; }
+ }
+
internal ArrayList Assemblies {
get {
if (appAssemblyIndex != -1) {
}
}
- internal ArrayList Interfaces {
- get { return interfaces; }
- }
-
internal RootBuilder RootBuilder {
- get { return rootBuilder; }
+ get {
+ if (rootBuilder != null)
+ return rootBuilder;
+ AspGenerator generator = AspGenerator;
+ if (generator != null)
+ rootBuilder = generator.RootBuilder;
+
+ return rootBuilder;
+ }
set { rootBuilder = value; }
}
get { return oc_duration; }
}
+ internal OutputCacheParsedParams OutputCacheParsedParameters {
+ get { return oc_parsed_params; }
+ }
+
+ internal string OutputCacheSqlDependency {
+ get { return oc_sqldependency; }
+ }
+
+ internal string OutputCacheCacheProfile {
+ get { return oc_cacheprofile; }
+ }
+
+ internal string OutputCacheVaryByContentEncodings {
+ get { return oc_content_encodings; }
+ }
+
+ internal bool OutputCacheNoStore {
+ get { return oc_nostore; }
+ }
+
+ internal virtual TextReader Reader {
+ get { return null; }
+ set { /* no-op */ }
+ }
+
internal string OutputCacheVaryByHeader {
get { return oc_header; }
}
get { return oc_param; }
}
-#if NET_2_0
+ internal List <string> RegisteredTagNames {
+ get { return registeredTagNames; }
+ }
+
internal PagesSection PagesConfig {
- get {
- return WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
- }
+ get { return GetConfigSection <PagesSection> ("system.web/pages") as PagesSection; }
}
-#else
- internal PagesConfiguration PagesConfig {
- get { return PagesConfiguration.GetInstance (Context); }
+
+ internal AspGenerator AspGenerator {
+ get;
+ set;
}
-#endif
}
-}
-
+}
\ No newline at end of file