2009-12-14 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspGenerator.cs
index d424109d37e5327355b68c06140370ab399e14a0..ed162cafeae522d7146a66b7a35e154bec9816f7 100644 (file)
@@ -31,6 +31,7 @@
 //
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.CodeDom.Compiler;
 using System.Globalization;
 using System.IO;
@@ -43,10 +44,6 @@ using System.Web.UI;
 using System.Web.UI.HtmlControls;
 using System.Web.Util;
 
-#if NET_2_0
-using System.Collections.Generic;
-#endif
-
 namespace System.Web.Compilation
 {
        class BuilderLocation
@@ -170,7 +167,7 @@ namespace System.Web.Compilation
                        if (tags.Count == 0)
                                return false;
 
-                       return 0 == String.Compare (tagid, (string) tags.Peek (), true, CultureInfo.InvariantCulture);
+                       return 0 == String.Compare (tagid, (string) tags.Peek (), true, Helpers.InvariantCulture);
                }
                
                public int Count {
@@ -211,11 +208,10 @@ namespace System.Web.Compilation
        
        class AspGenerator
        {
-#if NET_2_0
                const int READ_BUFFER_SIZE = 8192;
                
                internal static Regex DirectiveRegex = new Regex (@"<%\s*@(\s*(?<attrname>\w[\w:]*(?=\W))(\s*(?<equal>=)\s*""(?<attrval>[^""]*)""|\s*(?<equal>=)\s*'(?<attrval>[^']*)'|\s*(?<equal>=)\s*(?<attrval>[^\s%>]*)|(?<equal>)(?<attrval>\s*?)))*\s*?%>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
-#endif
+
                static readonly Regex runatServer = new Regex (@"<[\w:\.]+.*?runat=[""']?server[""']?.*?/?>",
                                                               RegexOptions.Compiled | RegexOptions.Singleline |
                                                               RegexOptions.Multiline | RegexOptions.IgnoreCase |
@@ -248,7 +244,6 @@ namespace System.Web.Compilation
                bool inForm;
                bool useOtherTags;
                TagType lastTag;
-#if NET_2_0
                AspComponentFoundry componentFoundry;
                Stream inputStream;
 
@@ -256,19 +251,12 @@ namespace System.Web.Compilation
                {
                        this.componentFoundry = componentFoundry;
                }
-#endif
                
                public AspGenerator (TemplateParser tparser)
                {
                        this.tparser = tparser;
                        text = new StringBuilder ();
                        stack = new BuilderLocationStack ();
-
-#if !NET_2_0
-                       rootBuilder = new RootBuilder (tparser);
-                       tparser.RootBuilder = rootBuilder;
-                       stack.Push (rootBuilder, null);
-#endif
                        pstack = new ParserStack ();
                }
 
@@ -284,7 +272,6 @@ namespace System.Web.Compilation
                        get { return pstack.Filename; }
                }
 
-#if NET_2_0
                PageParserFilter PageParserFilter {
                        get {
                                if (tparser == null)
@@ -384,7 +371,7 @@ namespace System.Web.Compilation
                        if (matches == null || matches.Count == 0)
                                return null;
 
-                       string wantedDirectiveName = tparser.DefaultDirectiveName.ToLower ();
+                       string wantedDirectiveName = tparser.DefaultDirectiveName.ToLower (Helpers.InvariantCulture);
                        string directiveName;
                        GroupCollection groups;
                        CaptureCollection ccNames;
@@ -399,7 +386,7 @@ namespace System.Web.Compilation
                                if (String.IsNullOrEmpty (directiveName))
                                        continue;
                                
-                               if (String.Compare (directiveName.ToLower (), wantedDirectiveName, StringComparison.Ordinal) != 0)
+                               if (String.Compare (directiveName.ToLower (Helpers.InvariantCulture), wantedDirectiveName, StringComparison.Ordinal) != 0)
                                        continue;
 
                                var loc = new Location (null);
@@ -523,7 +510,6 @@ namespace System.Web.Compilation
                        stack.Push (rootBuilder, null);
                        tparser.RootBuilder = rootBuilder;
                }
-#endif
                
                BaseCompiler GetCompilerFromType ()
                {
@@ -536,10 +522,9 @@ namespace System.Web.Compilation
 
                        if (type == typeof (UserControlParser))
                                return new UserControlCompiler ((UserControlParser) tparser);
-#if NET_2_0
+
                        if (type == typeof(MasterPageParser))
                                return new MasterPageCompiler ((MasterPageParser) tparser);
-#endif
 
                        throw new Exception ("Got type: " + type);
                }
@@ -550,11 +535,10 @@ namespace System.Web.Compilation
                        parser.Error += new ParseErrorHandler (ParseError);
                        parser.TagParsed += new TagParsedHandler (TagParsed);
                        parser.TextParsed += new TextParsedHandler (TextParsed);
-#if NET_2_0
                        parser.ParsingComplete += new ParsingCompleteHandler (ParsingCompleted);
                        tparser.AspGenerator = this;
                        CreateRootBuilder (inputStream, filename);
-#endif
+
                        if (!pstack.Push (parser))
                                throw new ParseException (Location, "Infinite recursion detected including file: " + filename);
 
@@ -567,13 +551,11 @@ namespace System.Web.Compilation
                        }
                }
                
-#if NET_2_0
                void InitParser (string filename)
                {
                        StreamReader reader = new StreamReader (filename, WebEncoding.FileEncoding);
                        InitParser (reader, filename);
                }
-#endif
 
                void CheckForDuplicateIds (ControlBuilder root, Stack scopes)
                {
@@ -581,27 +563,15 @@ namespace System.Web.Compilation
                                return;
                        
                        if (scopes == null)
-                               scopes = new Stack ();
-                       
-#if NET_2_0
+                               scopes = new Stack ();                  
+
                        Dictionary <string, bool> ids;
-#else
-                       Hashtable ids;
-#endif
                        
                        if (scopes.Count == 0 || root.IsNamingContainer) {
-#if NET_2_0
                                ids = new Dictionary <string, bool> (StringComparer.Ordinal);
-#else
-                               ids = new Hashtable ();
-#endif
                                scopes.Push (ids);
                        } else {
-#if NET_2_0
                                ids = scopes.Peek () as Dictionary <string, bool>;
-#else
-                               ids = scopes.Peek () as Hashtable;
-#endif
                        }
                        
                        if (ids == null)
@@ -631,11 +601,7 @@ namespace System.Web.Compilation
                
                public void Parse (string file)
                {
-#if ONLY_1_1
-                       Parse (file, true);
-#else
                        Parse (file, false);
-#endif
                }
                
                public void Parse (TextReader reader, string filename, bool doInitParser)
@@ -650,9 +616,7 @@ namespace System.Web.Compilation
                                if (text.Length > 0)
                                        FlushText ();
 
-#if NET_2_0
                                tparser.MD5Checksum = pstack.Parser.MD5Checksum;
-#endif
                                pstack.Pop ();
 
 #if DEBUG
@@ -672,9 +636,7 @@ namespace System.Web.Compilation
 
                public void Parse (Stream stream, string filename, bool doInitParser)
                {
-#if NET_2_0
                        inputStream = stream;
-#endif
                        Parse (new StreamReader (stream, WebEncoding.FileEncoding), filename, doInitParser);
                }
                
@@ -686,7 +648,6 @@ namespace System.Web.Compilation
 
                public void Parse ()
                {
-#if NET_2_0
                        string inputFile = tparser.InputFile;
                        TextReader inputReader = tparser.Reader;
 
@@ -716,9 +677,6 @@ namespace System.Web.Compilation
                                if (inputReader != null)
                                        inputReader.Close ();
                        }
-#else
-                       Parse (Path.GetFullPath (tparser.InputFile));
-#endif
                }
 
                internal static void AddTypeToCache (ArrayList dependencies, string inputFile, Type type)
@@ -750,7 +708,6 @@ namespace System.Web.Compilation
                        }
 
                        Parse ();
-
                        BaseCompiler compiler = GetCompilerFromType ();
                        
                        type = compiler.GetCompiledType ();
@@ -860,7 +817,9 @@ namespace System.Web.Compilation
 
                void ParseAttributeTag (string code, ILocation location)
                {
-                       AspParser parser = new AspParser ("@@attribute_tag@@", new StringReader (code), location.BeginLine - 1, location as AspParser);
+                       AspParser outerParser = location as AspParser;
+                       int positionOffset = outerParser != null ? outerParser.BeginPosition : 0;
+                       AspParser parser = new AspParser ("@@attribute_tag@@", new StringReader (code), location.BeginLine - 1, positionOffset, outerParser);
                        parser.Error += new ParseErrorHandler (ParseError);
                        parser.TagParsed += new TagParsedHandler (TagParsed);
                        parser.TextParsed += new TextParsedHandler (TextParsed);
@@ -869,7 +828,6 @@ namespace System.Web.Compilation
                                FlushText ();
                }
 
-#if NET_2_0
                void ParsingCompleted ()
                {
                        PageParserFilter pfilter = PageParserFilter;
@@ -878,7 +836,6 @@ namespace System.Web.Compilation
 
                        pfilter.ParseComplete (RootBuilder);
                }
-#endif
 
                void CheckIfIncludeFileIsSecure (string filePath)
                {
@@ -907,6 +864,17 @@ namespace System.Web.Compilation
                        if (exception != null || !StrUtils.StartsWith (newdir, HttpRuntime.AppDomainAppPath))
                                throw new ParseException (Location, "Files above the application's root directory cannot be included.");
                }
+
+               string ChopOffTagStart (ILocation location, string content, string tagid)
+               {
+                       string tagstart = '<' + tagid;
+                       if (content.StartsWith (tagstart)) {
+                               TextParsed (location, tagstart);
+                               content = content.Substring (tagstart.Length);
+                       }
+
+                       return content;
+               }
                
                void TagParsed (ILocation location, TagType tagtype, string tagid, TagAttributes attributes)
                {
@@ -919,7 +887,7 @@ namespace System.Web.Compilation
                        if (text.Length != 0)
                                FlushText (lastTag == TagType.CodeRender);
 
-                       if (0 == String.Compare (tagid, "script", true, CultureInfo.InvariantCulture)) {
+                       if (0 == String.Compare (tagid, "script", true, Helpers.InvariantCulture)) {
                                bool in_script = (inScript || ignore_text);
                                if (in_script) {
                                        if (ProcessScript (tagtype, attributes))
@@ -952,7 +920,7 @@ namespace System.Web.Compilation
                                {
                                        string plainText = location.PlainText;
                                        if (!ProcessTagsInAttributes (location, tagid, attributes, TagType.Tag))
-                                               TextParsed (location, plainText);
+                                               TextParsed (location, ChopOffTagStart (location, plainText, tagid));
                                }
                                break;
                        case TagType.Close:
@@ -967,7 +935,7 @@ namespace System.Web.Compilation
                                if (!ProcessTag (location, tagid, attributes, tagtype, out tagIgnored) && !tagIgnored) {
                                        string plainText = location.PlainText;
                                        if (!ProcessTagsInAttributes (location, tagid, attributes, TagType.SelfClosing))
-                                               TextParsed (location, plainText);
+                                               TextParsed (location, ChopOffTagStart (location, plainText, tagid));
                                } else if (stack.Count != count) {
                                        CloseControl (tagid);
                                }
@@ -993,7 +961,6 @@ namespace System.Web.Compilation
 
                                if (isvirtual) {
                                        bool parsed = false;
-#if NET_2_0
                                        VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
 
                                        if (vpp.FileExists (file)) {
@@ -1003,7 +970,6 @@ namespace System.Web.Compilation
                                                        parsed = true;
                                                }
                                        }
-#endif
                                        
                                        if (!parsed)
                                                Parse (tparser.MapPath (file), true);
@@ -1032,7 +998,7 @@ namespace System.Web.Compilation
 
                        for (int idx = otags.Count - 1; idx >= 0; idx--) {
                                string otagid = (string) otags [idx];
-                               if (0 == String.Compare (tagid, otagid, true, CultureInfo.InvariantCulture)) {
+                               if (0 == String.Compare (tagid, otagid, true, Helpers.InvariantCulture)) {
                                        do {
                                                otags.RemoveAt (idx);
                                        } while (otags.Count - 1 >= idx);
@@ -1057,19 +1023,9 @@ namespace System.Web.Compilation
                        return !text.EndsWith ("/>");
                }
                
-#if NET_2_0
-               List <TextBlock>
-#else
-               ArrayList
-#endif
-               FindRegexBlocks (Regex rxStart, Regex rxEnd, CheckBlockEnd checkEnd, IList blocks, TextBlockType typeForMatches, bool discardBlocks)
+               List <TextBlock> FindRegexBlocks (Regex rxStart, Regex rxEnd, CheckBlockEnd checkEnd, IList blocks, TextBlockType typeForMatches, bool discardBlocks)
                {
-#if NET_2_0
                        var ret = new List <TextBlock> ();
-#else
-                       ArrayList ret = new ArrayList ();
-#endif
-                       
                        foreach (TextBlock block in blocks) {
                                if (block.Type != TextBlockType.Verbatim) {
                                        ret.Add (block);
@@ -1110,11 +1066,7 @@ namespace System.Web.Compilation
                
                IList SplitTextIntoBlocks (string text)
                {
-#if NET_2_0
                        var ret = new List <TextBlock> ();
-#else
-                       ArrayList ret = new ArrayList ();
-#endif
 
                        ret.Add (new TextBlock (TextBlockType.Verbatim, text));
                        ret = FindRegexBlocks (clientCommentRegex, null, null, ret, TextBlockType.Comment, false);
@@ -1134,7 +1086,7 @@ namespace System.Web.Compilation
                                FlushText (true);
                                return;
                        }
-                       
+
                        IList blocks = SplitTextIntoBlocks (text);
                        foreach (TextBlock block in blocks) {
                                switch (block.Type) {
@@ -1156,14 +1108,23 @@ namespace System.Web.Compilation
                                        case TextBlockType.Comment: {
                                                this.text.Append ("<!--");
                                                FlushText (true);
-                                               AspParser parser = new AspParser ("@@comment_code@@",
-                                                                                 new StringReader (block.Content.Substring (4, block.Length - 7)),
-                                                                                 location.BeginLine - 1,
-                                                                                 location as AspParser);
+                                               string blockToParse = block.Content.Substring (4, block.Length - 7);
+                                               bool condEndif;
+                                               if (blockToParse.EndsWith ("<![endif]")) {
+                                                       blockToParse = blockToParse.Substring (0, blockToParse.Length - 9);
+                                                       condEndif = true;
+                                               } else
+                                                       condEndif = false;
+
+                                               AspParser outerParser = location as AspParser;
+                                               int positionOffset = outerParser != null ? outerParser.BeginPosition : 0;
+                                               AspParser parser = new AspParser ("@@comment_code@@", new StringReader (blockToParse), location.BeginLine - 1, positionOffset, outerParser);
                                                parser.Error += new ParseErrorHandler (ParseError);
                                                parser.TagParsed += new TagParsedHandler (TagParsed);
                                                parser.TextParsed += new TextParsedHandler (TextParsed);
                                                parser.Parse ();
+                                               if (condEndif)
+                                                       this.text.Append ("<![endif]");
                                                this.text.Append ("-->");
                                                FlushText (true);
                                                break;
@@ -1186,11 +1147,10 @@ namespace System.Web.Compilation
                                return;
                        
                        if (inScript) {
-#if NET_2_0
                                PageParserFilter pfilter = PageParserFilter;
                                if (pfilter != null && !pfilter.ProcessCodeConstruct (CodeConstructType.ScriptTag, t))
                                        return;
-#endif
+
                                tparser.Scripts.Add (new ServerSideScript (t, new System.Web.Compilation.Location (tparser.Location)));
                                return;
                        }
@@ -1205,7 +1165,6 @@ namespace System.Web.Compilation
                        }
                }
 
-#if NET_2_0
                bool BuilderHasOtherThan (Type type, ControlBuilder cb)
                {
                        ArrayList al = cb.OtherTags;
@@ -1253,7 +1212,6 @@ namespace System.Web.Compilation
                        
                        return true;
                }
-#endif
 
                public void AddControl (Type type, IDictionary attributes)
                {
@@ -1269,15 +1227,15 @@ namespace System.Web.Compilation
                {
                        ignored = false;
                        if (isApplication) {
-                               if (String.Compare (tagid, "object", true, CultureInfo.InvariantCulture) != 0)
+                               if (String.Compare (tagid, "object", true, Helpers.InvariantCulture) != 0)
                                        throw new ParseException (location, "Invalid tag for application file.");
                        }
 
                        ControlBuilder parent = stack.Builder;
                        ControlBuilder builder = null;
                        if (parent != null && parent.ControlType == typeof (HtmlTable) &&
-                           (String.Compare (tagid, "thead", true, CultureInfo.InvariantCulture) == 0 ||
-                            String.Compare (tagid, "tbody", true, CultureInfo.InvariantCulture) == 0)) {
+                           (String.Compare (tagid, "thead", true, Helpers.InvariantCulture) == 0 ||
+                            String.Compare (tagid, "tbody", true, Helpers.InvariantCulture) == 0)) {
                                ignored = true;
                                return true;
                        }
@@ -1322,14 +1280,13 @@ namespace System.Web.Compilation
                        string plainText = location.PlainText;
                        if (!runatServer && plainText.IndexOf ("<%$") == -1&& plainText.IndexOf ("<%") > -1)
                                return false;
-#if NET_2_0
+
                        PageParserFilter pfilter = PageParserFilter;
                        if (pfilter != null && !pfilter.AllowControl (builder.ControlType, builder))
                                throw new ParseException (Location, "Control type '" + builder.ControlType + "' not allowed.");
                        
                        if (!OtherControlsAllowed (builder))
                                throw new ParseException (Location, "Only Content controls are allowed directly in a content page that contains Content controls.");
-#endif
                        
                        builder.Location = location;
                        builder.ID = htable ["id"] as string;
@@ -1407,7 +1364,14 @@ namespace System.Web.Compilation
                                                Parser.VerbatimID = "script";
                                                javascript = true;
                                        }
-                                       TextParsed (location, location.PlainText);
+                                       string content = location.PlainText;
+                                       /* HACK, HACK, HACK */
+                                       if (content.StartsWith ("<script")) {
+                                               TextParsed (location, "<script");
+                                               content = content.Substring (7);
+                                       }
+
+                                       TextParsed (location, content);
                                        return true;
                                }
                        }
@@ -1432,8 +1396,8 @@ namespace System.Web.Compilation
                {
                        ControlBuilder current = stack.Builder;
                        string btag = current.OriginalTagName;
-                       if (String.Compare (btag, "tbody", true, CultureInfo.InvariantCulture) != 0 &&
-                           String.Compare (tagid, "tbody", true, CultureInfo.InvariantCulture) == 0) {
+                       if (String.Compare (btag, "tbody", true, Helpers.InvariantCulture) != 0 &&
+                           String.Compare (tagid, "tbody", true, Helpers.InvariantCulture) == 0) {
                                if (!current.ChildrenAsProperties) {
                                        try {
                                                TextParsed (location, location.PlainText);
@@ -1443,10 +1407,10 @@ namespace System.Web.Compilation
                                return true;
                        }
 
-                       if (current.ControlType == typeof (HtmlTable) && String.Compare (tagid, "thead", true, CultureInfo.InvariantCulture) == 0)
+                       if (current.ControlType == typeof (HtmlTable) && String.Compare (tagid, "thead", true, Helpers.InvariantCulture) == 0)
                                return true;
                        
-                       if (0 != String.Compare (tagid, btag, true, CultureInfo.InvariantCulture))
+                       if (0 != String.Compare (tagid, btag, true, Helpers.InvariantCulture))
                                return false;
 
                        // if (current is TemplateBuilder)
@@ -1471,7 +1435,6 @@ namespace System.Web.Compilation
                        return true;
                }
 
-#if NET_2_0
                CodeConstructType MapTagTypeToConstructType (TagType tagtype)
                {
                        switch (tagtype) {
@@ -1489,10 +1452,8 @@ namespace System.Web.Compilation
                        }
                }
                
-#endif
                bool ProcessCode (TagType tagtype, string code, ILocation location)
                {
-#if NET_2_0
                        PageParserFilter pfilter = PageParserFilter;
                        // LAMESPEC:
                        //
@@ -1505,7 +1466,7 @@ namespace System.Web.Compilation
                        //
                        if (pfilter != null && (!pfilter.AllowCode || pfilter.ProcessCodeConstruct (MapTagTypeToConstructType (tagtype), code)))
                                return true;
-#endif
+
                        ControlBuilder b = null;
                        if (tagtype == TagType.CodeRender)
                                b = new CodeRenderBuilder (code, false, location);
@@ -1529,16 +1490,11 @@ namespace System.Web.Compilation
                        if (lang == null || lang == "")
                                return;
 
-                       if (String.Compare (lang, tparser.Language, true, CultureInfo.InvariantCulture) == 0)
+                       if (String.Compare (lang, tparser.Language, true, Helpers.InvariantCulture) == 0)
                                return;
 
-#if NET_2_0
                        CompilationSection section = (CompilationSection) WebConfigurationManager.GetWebApplicationSection ("system.web/compilation");
                        if (section.Compilers[tparser.Language] != section.Compilers[lang])
-#else
-                       CompilationConfiguration cfg = CompilationConfiguration.GetInstance (HttpContext.Current); 
-                       if (!cfg.Compilers.CompareLanguages (tparser.Language, lang))
-#endif
                                throw new ParseException (Location,
                                                String.Format ("Trying to mix language '{0}' and '{1}'.", 
                                                                tparser.Language, lang));
@@ -1603,7 +1559,9 @@ namespace System.Web.Compilation
                        
                        void DoParse (string str)
                        {
-                               AspParser parser = new AspParser ("@@code_render@@", new StringReader (str), location.BeginLine - 1, location as AspParser);
+                               AspParser outerParser = location as AspParser;
+                               int positionOffset = outerParser != null ? outerParser.BeginPosition : 0;
+                               AspParser parser = new AspParser ("@@code_render@@", new StringReader (str), location.BeginLine - 1, positionOffset, outerParser);
                                parser.Error += new ParseErrorHandler (ParseError);
                                parser.TagParsed += new TagParsedHandler (TagParsed);
                                parser.TextParsed += new TextParsedHandler (TextParsed);