TemplateParser.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422
  1. //
  2. // System.Web.UI.TemplateParser
  3. //
  4. // Authors:
  5. // Duncan Mak ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Marek Habersack ([email protected])
  8. //
  9. // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
  10. // Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System.CodeDom.Compiler;
  32. using System.Collections;
  33. using System.ComponentModel;
  34. using System.Globalization;
  35. using System.IO;
  36. using System.Reflection;
  37. using System.Security.Permissions;
  38. using System.Text;
  39. using System.Threading;
  40. using System.Web.Compilation;
  41. using System.Web.Configuration;
  42. using System.Web.Hosting;
  43. using System.Web.Util;
  44. #if NET_2_0
  45. using System.Collections.Generic;
  46. #endif
  47. namespace System.Web.UI {
  48. internal class ServerSideScript
  49. {
  50. public readonly string Script;
  51. public readonly ILocation Location;
  52. public ServerSideScript (string script, ILocation location)
  53. {
  54. Script = script;
  55. Location = location;
  56. }
  57. }
  58. // CAS
  59. [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  60. [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  61. public abstract class TemplateParser : BaseParser
  62. {
  63. #if NET_2_0
  64. [Flags]
  65. internal enum OutputCacheParsedParams
  66. {
  67. Location = 0x0001,
  68. CacheProfile = 0x0002,
  69. NoStore = 0x0004,
  70. SqlDependency = 0x0008,
  71. VaryByCustom = 0x0010,
  72. VaryByHeader = 0x0020,
  73. VaryByControl = 0x0040,
  74. VaryByContentEncodings = 0x0080
  75. }
  76. #endif
  77. string inputFile;
  78. string text;
  79. Hashtable mainAttributes;
  80. ArrayList dependencies;
  81. ArrayList assemblies;
  82. Hashtable anames;
  83. #if NET_2_0
  84. string[] binDirAssemblies;
  85. Dictionary <string, bool> namespacesCache;
  86. List <string> imports;
  87. List <string> interfaces;
  88. List <ServerSideScript> scripts;
  89. #else
  90. ArrayList imports;
  91. ArrayList interfaces;
  92. ArrayList scripts;
  93. #endif
  94. Type baseType;
  95. bool baseTypeIsGlobal = true;
  96. string className;
  97. RootBuilder rootBuilder;
  98. bool debug;
  99. string compilerOptions;
  100. string language;
  101. bool implicitLanguage;
  102. bool strictOn ;
  103. bool explicitOn;
  104. bool linePragmasOn = true;
  105. bool output_cache;
  106. int oc_duration;
  107. string oc_header, oc_custom, oc_param, oc_controls;
  108. #if NET_2_0
  109. string oc_content_encodings, oc_cacheprofile, oc_sqldependency;
  110. bool oc_nostore;
  111. OutputCacheParsedParams oc_parsed_params = 0;
  112. #endif
  113. bool oc_shared;
  114. OutputCacheLocation oc_location;
  115. CultureInfo invariantCulture = CultureInfo.InvariantCulture;
  116. #if NET_2_0
  117. byte[] md5checksum;
  118. string src;
  119. bool srcIsLegacy;
  120. string partialClassName;
  121. string codeFileBaseClass;
  122. string metaResourceKey;
  123. Type codeFileBaseClassType;
  124. Type pageParserFilterType;
  125. PageParserFilter pageParserFilter;
  126. List <UnknownAttributeDescriptor> unknownMainAttributes;
  127. Stack <string> includeDirs;
  128. List <string> registeredTagNames;
  129. #else
  130. Stack includeDirs;
  131. Assembly srcAssembly;
  132. #endif
  133. ILocation directiveLocation;
  134. int appAssemblyIndex = -1;
  135. internal TemplateParser ()
  136. {
  137. LoadConfigDefaults ();
  138. #if NET_2_0
  139. imports = new List <string> ();
  140. AddNamespaces (imports);
  141. #else
  142. imports = new ArrayList ();
  143. imports.Add ("System");
  144. imports.Add ("System.Collections");
  145. imports.Add ("System.Collections.Specialized");
  146. imports.Add ("System.Configuration");
  147. imports.Add ("System.Text");
  148. imports.Add ("System.Text.RegularExpressions");
  149. imports.Add ("System.Web");
  150. imports.Add ("System.Web.Caching");
  151. imports.Add ("System.Web.Security");
  152. imports.Add ("System.Web.SessionState");
  153. imports.Add ("System.Web.UI");
  154. imports.Add ("System.Web.UI.WebControls");
  155. imports.Add ("System.Web.UI.HtmlControls");
  156. #endif
  157. assemblies = new ArrayList ();
  158. #if NET_2_0
  159. CompilationSection compConfig = CompilationConfig;
  160. foreach (AssemblyInfo info in compConfig.Assemblies) {
  161. if (info.Assembly != "*")
  162. AddAssemblyByName (info.Assembly);
  163. }
  164. foreach (NamespaceInfo info in PagesConfig.Namespaces) {
  165. imports.Add (info.Namespace);
  166. }
  167. #else
  168. CompilationConfiguration compConfig = CompilationConfig;
  169. foreach (string a in compConfig.Assemblies)
  170. AddAssemblyByName (a);
  171. if (compConfig.AssembliesInBin)
  172. AddAssembliesInBin ();
  173. #endif
  174. language = compConfig.DefaultLanguage;
  175. implicitLanguage = true;
  176. }
  177. internal virtual void LoadConfigDefaults ()
  178. {
  179. debug = CompilationConfig.Debug;
  180. }
  181. internal void AddApplicationAssembly ()
  182. {
  183. if (Context.ApplicationInstance == null)
  184. return; // this may happen if we have Global.asax and have
  185. // controls registered from Web.Config
  186. string location = Context.ApplicationInstance.AssemblyLocation;
  187. if (location != typeof (TemplateParser).Assembly.Location) {
  188. appAssemblyIndex = assemblies.Add (location);
  189. }
  190. }
  191. protected abstract Type CompileIntoType ();
  192. #if NET_2_0
  193. internal void AddControl (Type type, IDictionary attributes)
  194. {
  195. AspGenerator generator = AspGenerator;
  196. if (generator == null)
  197. return;
  198. generator.AddControl (type, attributes);
  199. }
  200. void AddNamespaces (List <string> imports)
  201. {
  202. if (BuildManager.HaveResources)
  203. imports.Add ("System.Resources");
  204. PagesSection pages = PagesConfig;
  205. if (pages == null)
  206. return;
  207. NamespaceCollection namespaces = pages.Namespaces;
  208. if (namespaces == null || namespaces.Count == 0)
  209. return;
  210. foreach (NamespaceInfo nsi in namespaces)
  211. imports.Add (nsi.Namespace);
  212. }
  213. #endif
  214. internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
  215. {
  216. string realpath = null;
  217. bool fileExists = false;
  218. #if NET_2_0
  219. VirtualFile vf = null;
  220. VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
  221. VirtualPath vp = new VirtualPath (src, BaseVirtualDir);
  222. string vpAbsolute = vp.Absolute;
  223. if (vpp.FileExists (vpAbsolute)) {
  224. fileExists = true;
  225. vf = vpp.GetFile (vpAbsolute);
  226. if (vf != null)
  227. realpath = MapPath (vf.VirtualPath);
  228. }
  229. #else
  230. realpath = MapPath (src);
  231. fileExists = File.Exists (realpath);
  232. #endif
  233. if (!fileExists)
  234. ThrowParseFileNotFound (src);
  235. if (String.Compare (realpath, inputFile, false, invariantCulture) == 0)
  236. return;
  237. #if NET_2_0
  238. string vpath = vf.VirtualPath;
  239. #else
  240. string vpath = VirtualPathUtility.Combine (BaseVirtualDir, src);
  241. if (VirtualPathUtility.IsAbsolute (vpath))
  242. vpath = VirtualPathUtility.ToAppRelative (vpath);
  243. #endif
  244. try {
  245. #if NET_2_0
  246. RegisterTagName (tagPrefix + ":" + tagName);
  247. RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, vpath);
  248. #else
  249. Type type = null;
  250. ArrayList other_deps = new ArrayList ();
  251. type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
  252. foreach (string s in other_deps)
  253. AddDependency (s);
  254. AddAssembly (type.Assembly, true);
  255. RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
  256. #endif
  257. AddDependency (vpath);
  258. } catch (ParseException pe) {
  259. if (this is UserControlParser)
  260. throw new ParseException (Location, pe.Message, pe);
  261. throw;
  262. }
  263. }
  264. internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
  265. {
  266. AddImport (ns);
  267. Assembly ass = null;
  268. if (assembly != null && assembly.Length > 0)
  269. ass = AddAssemblyByName (assembly);
  270. RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
  271. }
  272. internal virtual void HandleOptions (object obj)
  273. {
  274. }
  275. internal static string GetOneKey (Hashtable tbl)
  276. {
  277. foreach (object key in tbl.Keys)
  278. return key.ToString ();
  279. return null;
  280. }
  281. internal virtual void AddDirective (string directive, Hashtable atts)
  282. {
  283. #if NET_2_0
  284. var pageParserFilter = PageParserFilter;
  285. if (pageParserFilter != null)
  286. pageParserFilter.PreprocessDirective (directive.ToLower (CultureInfo.InvariantCulture), atts);
  287. #endif
  288. if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
  289. if (mainAttributes != null)
  290. ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
  291. mainAttributes = atts;
  292. ProcessMainAttributes (mainAttributes);
  293. return;
  294. }
  295. int cmp = String.Compare ("Assembly", directive, true);
  296. if (cmp == 0) {
  297. string name = GetString (atts, "Name", null);
  298. string src = GetString (atts, "Src", null);
  299. if (atts.Count > 0)
  300. ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
  301. if (name == null && src == null)
  302. ThrowParseException ("You gotta specify Src or Name");
  303. if (name != null && src != null)
  304. ThrowParseException ("Src and Name cannot be used together");
  305. if (name != null) {
  306. AddAssemblyByName (name);
  307. } else {
  308. GetAssemblyFromSource (src);
  309. }
  310. return;
  311. }
  312. cmp = String.Compare ("Import", directive, true);
  313. if (cmp == 0) {
  314. string namesp = GetString (atts, "Namespace", null);
  315. if (atts.Count > 0)
  316. ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
  317. AddImport (namesp);
  318. return;
  319. }
  320. cmp = String.Compare ("Implements", directive, true);
  321. if (cmp == 0) {
  322. string ifacename = GetString (atts, "Interface", "");
  323. if (atts.Count > 0)
  324. ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
  325. Type iface = LoadType (ifacename);
  326. if (iface == null)
  327. ThrowParseException ("Cannot find type " + ifacename);
  328. if (!iface.IsInterface)
  329. ThrowParseException (iface + " is not an interface");
  330. AddInterface (iface.FullName);
  331. return;
  332. }
  333. cmp = String.Compare ("OutputCache", directive, true);
  334. if (cmp == 0) {
  335. HttpResponse response = HttpContext.Current.Response;
  336. if (response != null)
  337. response.Cache.SetValidUntilExpires (true);
  338. output_cache = true;
  339. if (atts ["Duration"] == null)
  340. ThrowParseException ("The directive is missing a 'duration' attribute.");
  341. if (atts ["VaryByParam"] == null && atts ["VaryByControl"] == null)
  342. ThrowParseException ("This directive is missing 'VaryByParam' " +
  343. "or 'VaryByControl' attribute, which should be set to \"none\", \"*\", " +
  344. "or a list of name/value pairs.");
  345. foreach (DictionaryEntry entry in atts) {
  346. string key = (string) entry.Key;
  347. switch (key.ToLower ()) {
  348. case "duration":
  349. oc_duration = Int32.Parse ((string) entry.Value);
  350. if (oc_duration < 1)
  351. ThrowParseException ("The 'duration' attribute must be set " +
  352. "to a positive integer value");
  353. break;
  354. #if NET_2_0
  355. case "sqldependency":
  356. oc_sqldependency = (string) entry.Value;
  357. break;
  358. case "nostore":
  359. try {
  360. oc_nostore = Boolean.Parse ((string) entry.Value);
  361. oc_parsed_params |= OutputCacheParsedParams.NoStore;
  362. } catch {
  363. ThrowParseException ("The 'NoStore' attribute is case sensitive" +
  364. " and must be set to 'true' or 'false'.");
  365. }
  366. break;
  367. case "cacheprofile":
  368. oc_cacheprofile = (string) entry.Value;
  369. oc_parsed_params |= OutputCacheParsedParams.CacheProfile;
  370. break;
  371. case "varybycontentencodings":
  372. oc_content_encodings = (string) entry.Value;
  373. oc_parsed_params |= OutputCacheParsedParams.VaryByContentEncodings;
  374. break;
  375. #endif
  376. case "varybyparam":
  377. oc_param = (string) entry.Value;
  378. if (String.Compare (oc_param, "none") == 0)
  379. oc_param = null;
  380. break;
  381. case "varybyheader":
  382. oc_header = (string) entry.Value;
  383. #if NET_2_0
  384. oc_parsed_params |= OutputCacheParsedParams.VaryByHeader;
  385. #endif
  386. break;
  387. case "varybycustom":
  388. oc_custom = (string) entry.Value;
  389. #if NET_2_0
  390. oc_parsed_params |= OutputCacheParsedParams.VaryByCustom;
  391. #endif
  392. break;
  393. case "location":
  394. if (!(this is PageParser))
  395. goto default;
  396. try {
  397. oc_location = (OutputCacheLocation) Enum.Parse (
  398. typeof (OutputCacheLocation), (string) entry.Value, true);
  399. #if NET_2_0
  400. oc_parsed_params |= OutputCacheParsedParams.Location;
  401. #endif
  402. } catch {
  403. ThrowParseException ("The 'location' attribute is case sensitive and " +
  404. "must be one of the following values: Any, Client, " +
  405. "Downstream, Server, None, ServerAndClient.");
  406. }
  407. break;
  408. case "varybycontrol":
  409. #if ONLY_1_1
  410. if (this is PageParser)
  411. goto default;
  412. #endif
  413. oc_controls = (string) entry.Value;
  414. #if NET_2_0
  415. oc_parsed_params |= OutputCacheParsedParams.VaryByControl;
  416. #endif
  417. break;
  418. case "shared":
  419. if (this is PageParser)
  420. goto default;
  421. try {
  422. oc_shared = Boolean.Parse ((string) entry.Value);
  423. } catch {
  424. ThrowParseException ("The 'shared' attribute is case sensitive" +
  425. " and must be set to 'true' or 'false'.");
  426. }
  427. break;
  428. default:
  429. ThrowParseException ("The '" + key + "' attribute is not " +
  430. "supported by the 'Outputcache' directive.");
  431. break;
  432. }
  433. }
  434. return;
  435. }
  436. ThrowParseException ("Unknown directive: " + directive);
  437. }
  438. internal Type LoadType (string typeName)
  439. {
  440. Type type = HttpApplication.LoadType (typeName);
  441. if (type == null)
  442. return null;
  443. Assembly asm = type.Assembly;
  444. string location = asm.Location;
  445. string dirname = Path.GetDirectoryName (location);
  446. bool doAddAssembly = true;
  447. if (dirname == HttpApplication.BinDirectory)
  448. doAddAssembly = false;
  449. if (doAddAssembly)
  450. AddAssembly (asm, true);
  451. return type;
  452. }
  453. void AddAssembliesInBin ()
  454. {
  455. foreach (string s in HttpApplication.BinDirectoryAssemblies)
  456. assemblies.Add (s);
  457. }
  458. internal virtual void AddInterface (string iface)
  459. {
  460. if (interfaces == null) {
  461. #if NET_2_0
  462. interfaces = new List <string> ();
  463. #else
  464. interfaces = new ArrayList ();
  465. #endif
  466. }
  467. if (!interfaces.Contains (iface))
  468. interfaces.Add (iface);
  469. }
  470. internal virtual void AddImport (string namesp)
  471. {
  472. if (namesp == null || namesp.Length == 0)
  473. return;
  474. if (imports == null) {
  475. #if NET_2_0
  476. imports = new List <string> ();
  477. #else
  478. imports = new ArrayList ();
  479. #endif
  480. }
  481. if (imports.Contains (namesp))
  482. return;
  483. imports.Add (namesp);
  484. #if NET_2_0
  485. AddAssemblyForNamespace (namesp);
  486. #endif
  487. }
  488. #if NET_2_0
  489. void AddAssemblyForNamespace (string namesp)
  490. {
  491. if (binDirAssemblies == null)
  492. binDirAssemblies = HttpApplication.BinDirectoryAssemblies;
  493. if (binDirAssemblies.Length == 0)
  494. return;
  495. if (namespacesCache == null)
  496. namespacesCache = new Dictionary <string, bool> ();
  497. else if (namespacesCache.ContainsKey (namesp))
  498. return;
  499. foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
  500. if (FindNamespaceInAssembly (asm, namesp))
  501. return;
  502. IList tla = BuildManager.TopLevelAssemblies;
  503. if (tla != null && tla.Count > 0) {
  504. foreach (Assembly asm in tla) {
  505. if (FindNamespaceInAssembly (asm, namesp))
  506. return;
  507. }
  508. }
  509. Assembly a;
  510. foreach (string s in binDirAssemblies) {
  511. a = Assembly.LoadFrom (s);
  512. if (FindNamespaceInAssembly (a, namesp))
  513. return;
  514. }
  515. }
  516. bool FindNamespaceInAssembly (Assembly asm, string namesp)
  517. {
  518. foreach (Type type in asm.GetTypes ()) {
  519. if (String.Compare (type.Namespace, namesp, StringComparison.Ordinal) == 0) {
  520. namespacesCache.Add (namesp, true);
  521. AddAssembly (asm, true);
  522. return true;
  523. }
  524. }
  525. return false;
  526. }
  527. #endif
  528. internal virtual void AddSourceDependency (string filename)
  529. {
  530. if (dependencies != null && dependencies.Contains (filename))
  531. ThrowParseException ("Circular file references are not allowed. File: " + filename);
  532. AddDependency (filename);
  533. }
  534. internal virtual void AddDependency (string filename)
  535. {
  536. if (filename == null || filename == String.Empty)
  537. return;
  538. if (dependencies == null)
  539. dependencies = new ArrayList ();
  540. if (!dependencies.Contains (filename))
  541. dependencies.Add (filename);
  542. }
  543. internal virtual void AddAssembly (Assembly assembly, bool fullPath)
  544. {
  545. if (assembly == null || assembly.Location == String.Empty)
  546. return;
  547. if (anames == null)
  548. anames = new Hashtable ();
  549. string name = assembly.GetName ().Name;
  550. string loc = assembly.Location;
  551. if (fullPath) {
  552. if (!assemblies.Contains (loc)) {
  553. assemblies.Add (loc);
  554. }
  555. anames [name] = loc;
  556. anames [loc] = assembly;
  557. } else {
  558. if (!assemblies.Contains (name)) {
  559. assemblies.Add (name);
  560. }
  561. anames [name] = assembly;
  562. }
  563. }
  564. internal virtual Assembly AddAssemblyByFileName (string filename)
  565. {
  566. Assembly assembly = null;
  567. Exception error = null;
  568. try {
  569. assembly = Assembly.LoadFrom (filename);
  570. } catch (Exception e) { error = e; }
  571. if (assembly == null)
  572. ThrowParseException ("Assembly " + filename + " not found", error);
  573. AddAssembly (assembly, true);
  574. return assembly;
  575. }
  576. internal virtual Assembly AddAssemblyByName (string name)
  577. {
  578. if (anames == null)
  579. anames = new Hashtable ();
  580. if (anames.Contains (name)) {
  581. object o = anames [name];
  582. if (o is string)
  583. o = anames [o];
  584. return (Assembly) o;
  585. }
  586. Assembly assembly = null;
  587. Exception error = null;
  588. try {
  589. assembly = Assembly.Load (name);
  590. } catch (Exception e) { error = e; }
  591. if (assembly == null) {
  592. try {
  593. assembly = Assembly.LoadWithPartialName (name);
  594. } catch (Exception e) { error = e; }
  595. }
  596. if (assembly == null)
  597. ThrowParseException ("Assembly " + name + " not found", error);
  598. AddAssembly (assembly, true);
  599. return assembly;
  600. }
  601. internal virtual void ProcessMainAttributes (Hashtable atts)
  602. {
  603. directiveLocation = new System.Web.Compilation.Location (Location);
  604. #if NET_2_0
  605. CompilationSection compConfig;
  606. #else
  607. CompilationConfiguration compConfig;
  608. #endif
  609. compConfig = CompilationConfig;
  610. atts.Remove ("Description"); // ignored
  611. #if NET_1_1
  612. atts.Remove ("CodeBehind"); // ignored
  613. #endif
  614. atts.Remove ("AspCompat"); // ignored
  615. debug = GetBool (atts, "Debug", compConfig.Debug);
  616. compilerOptions = GetString (atts, "CompilerOptions", "");
  617. language = GetString (atts, "Language", "");
  618. if (language.Length != 0)
  619. implicitLanguage = false;
  620. else
  621. language = compConfig.DefaultLanguage;
  622. strictOn = GetBool (atts, "Strict", compConfig.Strict);
  623. explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
  624. if (atts.ContainsKey ("LinePragmas"))
  625. linePragmasOn = GetBool (atts, "LinePragmas", true);
  626. string inherits = GetString (atts, "Inherits", null);
  627. #if NET_2_0
  628. string srcRealPath = null;
  629. // In ASP 2, the source file is actually integrated with
  630. // the generated file via the use of partial classes. This
  631. // means that the code file has to be confirmed, but not
  632. // used at this point.
  633. src = GetString (atts, "CodeFile", null);
  634. codeFileBaseClass = GetString (atts, "CodeFileBaseClass", null);
  635. if (src == null && codeFileBaseClass != null)
  636. ThrowParseException ("The 'CodeFileBaseClass' attribute cannot be used without a 'CodeFile' attribute");
  637. string legacySrc = GetString (atts, "Src", null);
  638. if (legacySrc != null) {
  639. legacySrc = UrlUtils.Combine (BaseVirtualDir, legacySrc);
  640. GetAssemblyFromSource (legacySrc);
  641. if (src == null) {
  642. src = legacySrc;
  643. legacySrc = MapPath (legacySrc, false);
  644. srcRealPath = legacySrc;
  645. if (!File.Exists (srcRealPath))
  646. ThrowParseException ("File " + src + " not found");
  647. srcIsLegacy = true;
  648. } else
  649. legacySrc = MapPath (legacySrc, false);
  650. AddDependency (legacySrc);
  651. }
  652. if (!srcIsLegacy && src != null && inherits != null) {
  653. // Make sure the source exists
  654. src = UrlUtils.Combine (BaseVirtualDir, src);
  655. srcRealPath = MapPath (src, false);
  656. if (!HostingEnvironment.VirtualPathProvider.FileExists (src))
  657. ThrowParseException ("File " + src + " not found");
  658. // We are going to create a partial class that shares
  659. // the same name as the inherits tag, so reset the
  660. // name. The base type is changed because it is the
  661. // code file's responsibilty to extend the classes
  662. // needed.
  663. partialClassName = inherits;
  664. // Add the code file as an option to the
  665. // compiler. This lets both files be compiled at once.
  666. compilerOptions += " \"" + srcRealPath + "\"";
  667. if (codeFileBaseClass != null) {
  668. try {
  669. codeFileBaseClassType = LoadType (codeFileBaseClass);
  670. } catch (Exception) {
  671. }
  672. if (codeFileBaseClassType == null)
  673. ThrowParseException ("Could not load type '{0}'", codeFileBaseClass);
  674. }
  675. } else if (inherits != null) {
  676. // We just set the inherits directly because this is a
  677. // Single-Page model.
  678. SetBaseType (inherits);
  679. }
  680. #else
  681. string src = GetString (atts, "Src", null);
  682. if (src != null)
  683. srcAssembly = GetAssemblyFromSource (src);
  684. if (inherits != null)
  685. SetBaseType (inherits);
  686. #endif
  687. if (src != null) {
  688. if (VirtualPathUtility.IsAbsolute (src))
  689. src = VirtualPathUtility.ToAppRelative (src);
  690. AddDependency (src);
  691. }
  692. className = GetString (atts, "ClassName", null);
  693. if (className != null) {
  694. #if NET_2_0
  695. string [] identifiers = className.Split ('.');
  696. for (int i = 0; i < identifiers.Length; i++)
  697. if (!CodeGenerator.IsValidLanguageIndependentIdentifier (identifiers [i]))
  698. ThrowParseException (String.Format ("'{0}' is not a valid "
  699. + "value for attribute 'classname'.", className));
  700. #else
  701. if (!CodeGenerator.IsValidLanguageIndependentIdentifier (className))
  702. ThrowParseException (String.Format ("'{0}' is not a valid "
  703. + "value for attribute 'classname'.", className));
  704. #endif
  705. }
  706. #if NET_2_0
  707. if (this is TemplateControlParser)
  708. metaResourceKey = GetString (atts, "meta:resourcekey", null);
  709. if (inherits != null && (this is PageParser || this is UserControlParser) && atts.Count > 0) {
  710. if (unknownMainAttributes == null)
  711. unknownMainAttributes = new List <UnknownAttributeDescriptor> ();
  712. string key, val;
  713. foreach (DictionaryEntry de in atts) {
  714. key = de.Key as string;
  715. val = de.Value as string;
  716. if (String.IsNullOrEmpty (key) || String.IsNullOrEmpty (val))
  717. continue;
  718. CheckUnknownAttribute (key, val, inherits);
  719. }
  720. return;
  721. }
  722. #endif
  723. if (atts.Count > 0)
  724. ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
  725. }
  726. #if NET_2_0
  727. void RegisterTagName (string tagName)
  728. {
  729. if (registeredTagNames == null)
  730. registeredTagNames = new List <string> ();
  731. if (registeredTagNames.Contains (tagName))
  732. return;
  733. registeredTagNames.Add (tagName);
  734. }
  735. void CheckUnknownAttribute (string name, string val, string inherits)
  736. {
  737. MemberInfo mi = null;
  738. bool missing = false;
  739. string memberName = name.Trim ().ToLower (CultureInfo.InvariantCulture);
  740. Type parent = codeFileBaseClassType;
  741. if (parent == null)
  742. parent = baseType;
  743. try {
  744. MemberInfo[] infos = parent.GetMember (memberName,
  745. MemberTypes.Field | MemberTypes.Property,
  746. BindingFlags.Public | BindingFlags.Instance |
  747. BindingFlags.IgnoreCase | BindingFlags.Static);
  748. if (infos.Length != 0) {
  749. // prefer public properties to public methods (it's what MS.NET does)
  750. foreach (MemberInfo tmp in infos) {
  751. if (tmp is PropertyInfo) {
  752. mi = tmp;
  753. break;
  754. }
  755. }
  756. if (mi == null)
  757. mi = infos [0];
  758. } else
  759. missing = true;
  760. } catch (Exception) {
  761. missing = true;
  762. }
  763. if (missing)
  764. ThrowParseException (
  765. "Error parsing attribute '{0}': Type '{1}' does not have a public property named '{0}'",
  766. memberName, inherits);
  767. Type memberType = null;
  768. if (mi is PropertyInfo) {
  769. PropertyInfo pi = mi as PropertyInfo;
  770. if (!pi.CanWrite)
  771. ThrowParseException (
  772. "Error parsing attribute '{0}': The '{0}' property is read-only and cannot be set.",
  773. memberName);
  774. memberType = pi.PropertyType;
  775. } else if (mi is FieldInfo) {
  776. memberType = ((FieldInfo)mi).FieldType;
  777. } else
  778. ThrowParseException ("Could not determine member the kind of '{0}' in base type '{1}",
  779. memberName, inherits);
  780. TypeConverter converter = TypeDescriptor.GetConverter (memberType);
  781. bool convertible = true;
  782. object value = null;
  783. if (converter == null || !converter.CanConvertFrom (typeof (string)))
  784. convertible = false;
  785. if (convertible) {
  786. try {
  787. value = converter.ConvertFromInvariantString (val);
  788. } catch (Exception) {
  789. convertible = false;
  790. }
  791. }
  792. if (!convertible)
  793. ThrowParseException ("Error parsing attribute '{0}': Cannot create an object of type '{1}' from its string representation '{2}' for the '{3}' property.",
  794. memberName, memberType, val, mi.Name);
  795. UnknownAttributeDescriptor desc = new UnknownAttributeDescriptor (mi, value);
  796. unknownMainAttributes.Add (desc);
  797. }
  798. #endif
  799. internal void SetBaseType (string type)
  800. {
  801. Type parent;
  802. if (type == null || type == DefaultBaseTypeName)
  803. parent = DefaultBaseType;
  804. else
  805. parent = null;
  806. if (parent == null) {
  807. #if NET_2_0
  808. parent = LoadType (type);
  809. #else
  810. parent = null;
  811. if (srcAssembly != null)
  812. parent = srcAssembly.GetType (type);
  813. if (parent == null)
  814. parent = LoadType (type);
  815. #endif
  816. if (parent == null)
  817. ThrowParseException ("Cannot find type " + type);
  818. if (!DefaultBaseType.IsAssignableFrom (parent))
  819. ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
  820. }
  821. #if NET_2_0
  822. var pageParserFilter = PageParserFilter;
  823. if (pageParserFilter != null && !pageParserFilter.AllowBaseType (parent))
  824. throw new HttpException ("Base type '" + parent + "' is not allowed.");
  825. #endif
  826. baseType = parent;
  827. }
  828. internal void SetLanguage (string language)
  829. {
  830. this.language = language;
  831. implicitLanguage = false;
  832. }
  833. internal void PushIncludeDir (string dir)
  834. {
  835. if (includeDirs == null) {
  836. #if NET_2_0
  837. includeDirs = new Stack <string> (1);
  838. #else
  839. includeDirs = new Stack (1);
  840. #endif
  841. }
  842. includeDirs.Push (dir);
  843. }
  844. internal string PopIncludeDir ()
  845. {
  846. if (includeDirs == null || includeDirs.Count == 0)
  847. return null;
  848. return includeDirs.Pop () as string;
  849. }
  850. Assembly GetAssemblyFromSource (string vpath)
  851. {
  852. vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
  853. string realPath = MapPath (vpath, false);
  854. if (!File.Exists (realPath))
  855. ThrowParseException ("File " + vpath + " not found");
  856. AddSourceDependency (vpath);
  857. CompilerResults result;
  858. #if NET_2_0
  859. string tmp;
  860. CompilerParameters parameters;
  861. CodeDomProvider provider = BaseCompiler.CreateProvider (HttpContext.Current, language, out parameters, out tmp);
  862. if (provider == null)
  863. throw new HttpException ("Cannot find provider for language '" + language + "'.");
  864. AssemblyBuilder abuilder = new AssemblyBuilder (provider);
  865. abuilder.CompilerOptions = parameters;
  866. abuilder.AddAssemblyReference (BuildManager.GetReferencedAssemblies () as List <Assembly>);
  867. abuilder.AddCodeFile (realPath);
  868. result = abuilder.BuildAssembly (new VirtualPath (vpath));
  869. #else
  870. result = CachingCompiler.Compile (language, realPath, realPath, assemblies, Debug);
  871. #endif
  872. if (result.NativeCompilerReturnValue != 0) {
  873. using (StreamReader reader = new StreamReader (realPath)) {
  874. throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
  875. }
  876. }
  877. AddAssembly (result.CompiledAssembly, true);
  878. return result.CompiledAssembly;
  879. }
  880. internal abstract string DefaultBaseTypeName { get; }
  881. internal abstract string DefaultDirectiveName { get; }
  882. internal bool LinePragmasOn {
  883. get { return linePragmasOn; }
  884. }
  885. #if NET_2_0
  886. internal byte[] MD5Checksum {
  887. get { return md5checksum; }
  888. set { md5checksum = value; }
  889. }
  890. internal PageParserFilter PageParserFilter {
  891. get {
  892. if (pageParserFilter != null)
  893. return pageParserFilter;
  894. Type t = PageParserFilterType;
  895. if (t == null)
  896. return null;
  897. pageParserFilter = Activator.CreateInstance (t) as PageParserFilter;
  898. pageParserFilter.Initialize (this);
  899. return pageParserFilter;
  900. }
  901. }
  902. internal Type PageParserFilterType {
  903. get {
  904. if (pageParserFilterType == null) {
  905. string typeName = PagesConfig.PageParserFilterType;
  906. if (String.IsNullOrEmpty (typeName))
  907. return null;
  908. pageParserFilterType = Type.GetType (typeName, true);
  909. }
  910. return pageParserFilterType;
  911. }
  912. }
  913. #endif
  914. internal Type DefaultBaseType {
  915. get {
  916. Type type = Type.GetType (DefaultBaseTypeName, true);
  917. return type;
  918. }
  919. }
  920. internal ILocation DirectiveLocation {
  921. get { return directiveLocation; }
  922. }
  923. internal string ParserDir {
  924. get {
  925. if (includeDirs == null || includeDirs.Count == 0)
  926. return BaseDir;
  927. return includeDirs.Peek () as string;
  928. }
  929. }
  930. internal string InputFile
  931. {
  932. get { return inputFile; }
  933. set { inputFile = value; }
  934. }
  935. #if NET_2_0
  936. internal bool IsPartial {
  937. get { return (!srcIsLegacy && src != null); }
  938. }
  939. internal string CodeBehindSource {
  940. get {
  941. if (srcIsLegacy)
  942. return null;
  943. return src;
  944. }
  945. }
  946. internal string PartialClassName {
  947. get { return partialClassName; }
  948. }
  949. internal string CodeFileBaseClass {
  950. get { return codeFileBaseClass; }
  951. }
  952. internal string MetaResourceKey {
  953. get { return metaResourceKey; }
  954. }
  955. internal Type CodeFileBaseClassType
  956. {
  957. get { return codeFileBaseClassType; }
  958. }
  959. internal List <UnknownAttributeDescriptor> UnknownMainAttributes
  960. {
  961. get { return unknownMainAttributes; }
  962. }
  963. #endif
  964. internal string Text {
  965. get { return text; }
  966. set { text = value; }
  967. }
  968. internal Type BaseType {
  969. get {
  970. if (baseType == null)
  971. SetBaseType (DefaultBaseTypeName);
  972. return baseType;
  973. }
  974. }
  975. internal bool BaseTypeIsGlobal {
  976. get { return baseTypeIsGlobal; }
  977. set { baseTypeIsGlobal = value; }
  978. }
  979. #if NET_2_0
  980. static long autoClassCounter = 0;
  981. #endif
  982. internal string EncodeIdentifier (string value)
  983. {
  984. if (value == null || value.Length == 0 || CodeGenerator.IsValidLanguageIndependentIdentifier (value))
  985. return value;
  986. StringBuilder ret = new StringBuilder ();
  987. char ch = value [0];
  988. switch (Char.GetUnicodeCategory (ch)) {
  989. case UnicodeCategory.LetterNumber:
  990. case UnicodeCategory.LowercaseLetter:
  991. case UnicodeCategory.TitlecaseLetter:
  992. case UnicodeCategory.UppercaseLetter:
  993. case UnicodeCategory.OtherLetter:
  994. case UnicodeCategory.ModifierLetter:
  995. case UnicodeCategory.ConnectorPunctuation:
  996. ret.Append (ch);
  997. break;
  998. case UnicodeCategory.DecimalDigitNumber:
  999. ret.Append ('_');
  1000. ret.Append (ch);
  1001. break;
  1002. default:
  1003. ret.Append ('_');
  1004. break;
  1005. }
  1006. for (int i = 1; i < value.Length; i++) {
  1007. ch = value [i];
  1008. switch (Char.GetUnicodeCategory (ch)) {
  1009. case UnicodeCategory.LetterNumber:
  1010. case UnicodeCategory.LowercaseLetter:
  1011. case UnicodeCategory.TitlecaseLetter:
  1012. case UnicodeCategory.UppercaseLetter:
  1013. case UnicodeCategory.OtherLetter:
  1014. case UnicodeCategory.ModifierLetter:
  1015. case UnicodeCategory.ConnectorPunctuation:
  1016. case UnicodeCategory.DecimalDigitNumber:
  1017. case UnicodeCategory.NonSpacingMark:
  1018. case UnicodeCategory.SpacingCombiningMark:
  1019. case UnicodeCategory.Format:
  1020. ret.Append (ch);
  1021. break;
  1022. default:
  1023. ret.Append ('_');
  1024. break;
  1025. }
  1026. }
  1027. return ret.ToString ();
  1028. }
  1029. internal string ClassName {
  1030. get {
  1031. if (className != null)
  1032. return className;
  1033. #if NET_2_0
  1034. string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
  1035. string inFile;
  1036. if (String.IsNullOrEmpty (inputFile)) {
  1037. inFile = null;
  1038. using (StreamReader sr = Reader as StreamReader) {
  1039. if (sr != null) {
  1040. FileStream fr = sr.BaseStream as FileStream;
  1041. if (fr != null)
  1042. inFile = fr.Name;
  1043. }
  1044. }
  1045. } else
  1046. inFile = inputFile;
  1047. if (String.IsNullOrEmpty (inFile)) {
  1048. // generate a unique class name
  1049. long suffix;
  1050. suffix = Interlocked.Increment (ref autoClassCounter);
  1051. className = String.Format ("autoclass_nosource_{0:x}", suffix);
  1052. return className;
  1053. }
  1054. if (StrUtils.StartsWith (inFile, physPath))
  1055. className = inputFile.Substring (physPath.Length).ToLower (CultureInfo.InvariantCulture);
  1056. else
  1057. #endif
  1058. className = Path.GetFileName (inputFile);
  1059. className = EncodeIdentifier (className);
  1060. return className;
  1061. }
  1062. }
  1063. #if NET_2_0
  1064. internal List <ServerSideScript> Scripts {
  1065. get {
  1066. if (scripts == null)
  1067. scripts = new List <ServerSideScript> ();
  1068. return scripts;
  1069. }
  1070. }
  1071. internal List <string> Imports {
  1072. get { return imports; }
  1073. }
  1074. internal List <string> Interfaces {
  1075. get { return interfaces; }
  1076. }
  1077. #else
  1078. internal ArrayList Scripts {
  1079. get {
  1080. if (scripts == null)
  1081. scripts = new ArrayList ();
  1082. return scripts;
  1083. }
  1084. }
  1085. internal ArrayList Imports {
  1086. get { return imports; }
  1087. }
  1088. internal ArrayList Interfaces {
  1089. get { return interfaces; }
  1090. }
  1091. #endif
  1092. internal ArrayList Assemblies {
  1093. get {
  1094. if (appAssemblyIndex != -1) {
  1095. object o = assemblies [appAssemblyIndex];
  1096. assemblies.RemoveAt (appAssemblyIndex);
  1097. assemblies.Add (o);
  1098. appAssemblyIndex = -1;
  1099. }
  1100. return assemblies;
  1101. }
  1102. }
  1103. internal RootBuilder RootBuilder {
  1104. get { return rootBuilder; }
  1105. set { rootBuilder = value; }
  1106. }
  1107. internal ArrayList Dependencies {
  1108. get { return dependencies; }
  1109. set { dependencies = value; }
  1110. }
  1111. internal string CompilerOptions {
  1112. get { return compilerOptions; }
  1113. }
  1114. internal string Language {
  1115. get { return language; }
  1116. }
  1117. internal bool ImplicitLanguage {
  1118. get { return implicitLanguage; }
  1119. }
  1120. internal bool StrictOn {
  1121. get { return strictOn; }
  1122. }
  1123. internal bool ExplicitOn {
  1124. get { return explicitOn; }
  1125. }
  1126. internal bool Debug {
  1127. get { return debug; }
  1128. }
  1129. internal bool OutputCache {
  1130. get { return output_cache; }
  1131. }
  1132. internal int OutputCacheDuration {
  1133. get { return oc_duration; }
  1134. }
  1135. #if NET_2_0
  1136. internal OutputCacheParsedParams OutputCacheParsedParameters {
  1137. get { return oc_parsed_params; }
  1138. }
  1139. internal string OutputCacheSqlDependency {
  1140. get { return oc_sqldependency; }
  1141. }
  1142. internal string OutputCacheCacheProfile {
  1143. get { return oc_cacheprofile; }
  1144. }
  1145. internal string OutputCacheVaryByContentEncodings {
  1146. get { return oc_content_encodings; }
  1147. }
  1148. internal bool OutputCacheNoStore {
  1149. get { return oc_nostore; }
  1150. }
  1151. internal virtual TextReader Reader {
  1152. get { return null; }
  1153. set { /* no-op */ }
  1154. }
  1155. #endif
  1156. internal string OutputCacheVaryByHeader {
  1157. get { return oc_header; }
  1158. }
  1159. internal string OutputCacheVaryByCustom {
  1160. get { return oc_custom; }
  1161. }
  1162. internal string OutputCacheVaryByControls {
  1163. get { return oc_controls; }
  1164. }
  1165. internal bool OutputCacheShared {
  1166. get { return oc_shared; }
  1167. }
  1168. internal OutputCacheLocation OutputCacheLocation {
  1169. get { return oc_location; }
  1170. }
  1171. internal string OutputCacheVaryByParam {
  1172. get { return oc_param; }
  1173. }
  1174. #if NET_2_0
  1175. internal List <string> RegisteredTagNames {
  1176. get { return registeredTagNames; }
  1177. }
  1178. internal PagesSection PagesConfig {
  1179. get { return GetConfigSection <PagesSection> ("system.web/pages") as PagesSection; }
  1180. }
  1181. internal AspGenerator AspGenerator {
  1182. get;
  1183. set;
  1184. }
  1185. #else
  1186. internal PagesConfiguration PagesConfig {
  1187. get { return PagesConfiguration.GetInstance (Context); }
  1188. }
  1189. #endif
  1190. }
  1191. }