2008-11-18 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspParser.cs
index ab1f15034236785dd6f878a15c81433802b632ed..6e53749095d4f7cd824a7f90b21423cbcfad8598 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
 {
@@ -40,6 +44,13 @@ 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 ();
+
+#if NET_2_0
+               byte[] md5checksum;
+#endif
                AspTokenizer tokenizer;
                int beginLine, endLine;
                int beginColumn, endColumn;
@@ -48,14 +59,41 @@ namespace System.Web.Compilation
                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; }
                }
@@ -72,6 +110,10 @@ namespace System.Web.Compilation
                        get { return endColumn; }
                }
 
+               public string FileText {
+                       get { return fileText; }
+               }
+               
                public string PlainText {
                        get {
                                if (beginPosition >= endPosition)
@@ -88,7 +130,7 @@ namespace System.Web.Compilation
                public string VerbatimID {
                        set {
                                tokenizer.Verbatim = true;
-                               verbatimID = value.ToUpper ();
+                               verbatimID = value;
                        }
                }
                
@@ -187,12 +229,12 @@ namespace System.Web.Compilation
                        if (len < 10 || lastQuote != len - 1)
                                return false;
 
-                       if (!str.ToLower ().StartsWith ("#include "))
+                       if (!StrUtils.StartsWith (str, "#include ", true))
                                return false;
 
                        str = str.Substring (9).Trim ();
-                       bool isfile = (str.ToLower ().StartsWith ("file"));
-                       if (!isfile && !str.ToLower ().StartsWith ("virtual"))
+                       bool isfile = (StrUtils.StartsWith (str ,"file", true));
+                       if (!isfile && !StrUtils.StartsWith (str, "virtual", true))
                                return false;
 
                        pathType = (isfile) ? "file" : "virtual";
@@ -206,7 +248,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;
                        }
@@ -313,6 +355,7 @@ namespace System.Web.Compilation
                        int token;
                        TagAttributes attributes;
                        string id;
+                       bool wellFormedForServer = true;
 
                        attributes = new TagAttributes ();
                        while ((token = tokenizer.get_token ()) != Token.EOF){
@@ -332,6 +375,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, "<%" + 
@@ -348,12 +392,19 @@ namespace System.Web.Compilation
                        }
 
                        tokenizer.put_back ();
+
+                       if (attributes.IsRunAtServer () && !wellFormedForServer) {
+                               OnError ("The server tag is not well formed.");
+                               return null;
+                       }
+                       
                        return attributes;
                }
 
                string GetVerbatim (int token, string end)
                {
                        StringBuilder vb_text = new StringBuilder ();
+                       StringBuilder tmp = new StringBuilder ();
                        int i = 0;
 
                        if (tokenizer.Value.Length > 1){
@@ -362,15 +413,18 @@ namespace System.Web.Compilation
                                token = tokenizer.get_token ();
                        }
 
+                       end = end.ToLower (CultureInfo.InvariantCulture);
+                       
                        while (token != Token.EOF){
-                               if (Char.ToUpper ((char) token) == end [i]){
+                               if (Char.ToLower ((char) token, CultureInfo.InvariantCulture) == end [i]){
                                        if (++i >= end.Length)
                                                break;
+                                       tmp.Append ((char) token);
                                        token = tokenizer.get_token ();
                                        continue;
                                } else if (i > 0) {
-                                       for (int j = 0; j < i; j++)
-                                               vb_text.Append (end [j]);
+                                       vb_text.Append (tmp.ToString ());
+                                       tmp.Remove (0, tmp.Length);
                                        i = 0;
                                }
 
@@ -378,6 +432,9 @@ namespace System.Web.Compilation
                                token = tokenizer.get_token ();
                        } 
 
+                       if (token == Token.EOF)
+                               OnError ("Expecting " + end + " and got EOF.");
+
                        return RemoveComments (vb_text.ToString ());
                }
 
@@ -444,26 +501,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);
                }
        }