Revert r106068 and reopen bug #400807. The revision broke more than it fixed and...
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspParser.cs
index 87c88456f377140c89024a1d64f8c8676024aedc..004d9732ee3ba569e17e665958846f3e634a51ea 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 using System;
+using System.ComponentModel;
 using System.Collections;
 using System.Globalization;
 using System.IO;
 using System.Text;
+using System.Web.Util;
+using System.Security.Cryptography;
 
 namespace System.Web.Compilation
 {
@@ -41,22 +44,54 @@ namespace System.Web.Compilation
 
        class AspParser : ILocation
        {
+               static readonly object errorEvent = new object ();
+               static readonly object tagParsedEvent = new object ();
+               static readonly object textParsedEvent = new object ();
+               
                AspTokenizer tokenizer;
                int beginLine, endLine;
                int beginColumn, endColumn;
                int beginPosition, endPosition;
+               byte[] md5checksum;
                string filename;
                string fileText;
                string verbatimID;
 
+               EventHandlerList events = new EventHandlerList ();
+               
+               public event ParseErrorHandler Error {
+                       add { events.AddHandler (errorEvent, value); }
+                       remove { events.RemoveHandler (errorEvent, value); }
+               }
+               
+               public event TagParsedHandler TagParsed {
+                       add { events.AddHandler (tagParsedEvent, value); }
+                       remove { events.RemoveHandler (tagParsedEvent, value); }
+               }
+               
+               public event TextParsedHandler TextParsed {
+                       add { events.AddHandler (textParsedEvent, value); }
+                       remove { events.RemoveHandler (textParsedEvent, value); }
+               }
+
                public AspParser (string filename, TextReader input)
                {
                        this.filename = filename;
                        fileText = input.ReadToEnd ();
+#if NET_2_0
+                       MD5 md5 = MD5.Create ();
+                       md5checksum = md5.ComputeHash (Encoding.UTF8.GetBytes (fileText));
+#endif
                        StringReader reader = new StringReader (fileText);
                        tokenizer = new AspTokenizer (reader);
                }
 
+#if NET_2_0
+               public byte[] MD5Checksum {
+                       get { return md5checksum; }
+               }
+#endif
+               
                public int BeginLine {
                        get { return beginLine; }
                }
@@ -73,6 +108,10 @@ namespace System.Web.Compilation
                        get { return endColumn; }
                }
 
+               public string FileText {
+                       get { return fileText; }
+               }
+               
                public string PlainText {
                        get {
                                if (beginPosition >= endPosition)
@@ -89,7 +128,7 @@ namespace System.Web.Compilation
                public string VerbatimID {
                        set {
                                tokenizer.Verbatim = true;
-                               verbatimID = value.ToUpper (CultureInfo.InvariantCulture);
+                               verbatimID = value;
                        }
                }
                
@@ -188,12 +227,12 @@ namespace System.Web.Compilation
                        if (len < 10 || lastQuote != len - 1)
                                return false;
 
-                       if (!str.ToLower (CultureInfo.InvariantCulture).StartsWith ("#include "))
+                       if (!StrUtils.StartsWith (str, "#include ", true))
                                return false;
 
                        str = str.Substring (9).Trim ();
-                       bool isfile = (str.ToLower (CultureInfo.InvariantCulture).StartsWith ("file"));
-                       if (!isfile && !str.ToLower (CultureInfo.InvariantCulture).StartsWith ("virtual"))
+                       bool isfile = (StrUtils.StartsWith (str ,"file", true));
+                       if (!isfile && !StrUtils.StartsWith (str, "virtual", true))
                                return false;
 
                        pathType = (isfile) ? "file" : "virtual";
@@ -207,7 +246,7 @@ namespace System.Web.Compilation
                        int index = 1;
                        for (; index < str.Length; index++) {
                                if (Char.IsWhiteSpace (str [index]))
-                                       index++;
+                                       continue;
                                else if (str [index] == '"')
                                        break;
                        }
@@ -314,6 +353,7 @@ namespace System.Web.Compilation
                        int token;
                        TagAttributes attributes;
                        string id;
+                       bool wellFormedForServer = true;
 
                        attributes = new TagAttributes ();
                        while ((token = tokenizer.get_token ()) != Token.EOF){
@@ -333,6 +373,7 @@ namespace System.Web.Compilation
                                if (Eat ('=')){
                                        if (Eat (Token.ATTVALUE)){
                                                attributes.Add (id, tokenizer.Value);
+                                               wellFormedForServer &= tokenizer.AlternatingQuotes;
                                        } else if (Eat ('<') && Eat ('%')) {
                                                tokenizer.Verbatim = true;
                                                attributes.Add (id, "<%" + 
@@ -349,6 +390,12 @@ namespace System.Web.Compilation
                        }
 
                        tokenizer.put_back ();
+
+                       if (attributes.IsRunAtServer () && !wellFormedForServer) {
+                               OnError ("The server tag is not well formed.");
+                               return null;
+                       }
+                       
                        return attributes;
                }
 
@@ -363,8 +410,9 @@ namespace System.Web.Compilation
                                token = tokenizer.get_token ();
                        }
 
+                       end = end.ToLower (CultureInfo.InvariantCulture);
                        while (token != Token.EOF){
-                               if (Char.ToUpper ((char) token, CultureInfo.InvariantCulture) == end [i]){
+                               if (Char.ToLower ((char) token, CultureInfo.InvariantCulture) == end [i]){
                                        if (++i >= end.Length)
                                                break;
                                        token = tokenizer.get_token ();
@@ -379,6 +427,9 @@ namespace System.Web.Compilation
                                token = tokenizer.get_token ();
                        } 
 
+                       if (token == Token.EOF)
+                               OnError ("Expecting " + end + " and got EOF.");
+
                        return RemoveComments (vb_text.ToString ());
                }
 
@@ -445,26 +496,25 @@ namespace System.Web.Compilation
                                  (varname ? TagType.CodeRenderExpression : TagType.CodeRender));
                }
 
-               public event ParseErrorHandler Error;
-               public event TagParsedHandler TagParsed;
-               public event TextParsedHandler TextParsed;
-
                void OnError (string msg)
                {
-                       if (Error != null)
-                               Error (this, msg);
+                       ParseErrorHandler eh = events [errorEvent] as ParseErrorHandler;
+                       if (eh != null)
+                               eh (this, msg);
                }
 
                void OnTagParsed (TagType tagtype, string id, TagAttributes attributes)
                {
-                       if (TagParsed != null)
-                               TagParsed (this, tagtype, id, attributes);
+                       TagParsedHandler eh = events [tagParsedEvent] as TagParsedHandler;
+                       if (eh != null)
+                               eh (this, tagtype, id, attributes);
                }
 
                void OnTextParsed (string text)
                {
-                       if (TextParsed != null)
-                               TextParsed (this, text);
+                       TextParsedHandler eh = events [textParsedEvent] as TextParsedHandler;
+                       if (eh != null)
+                               eh (this, text);
                }
        }