// 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
{
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;
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; }
}
get { return endColumn; }
}
+ public string FileText {
+ get { return fileText; }
+ }
+
public string PlainText {
get {
if (beginPosition >= endPosition)
public string VerbatimID {
set {
tokenizer.Verbatim = true;
- verbatimID = value.ToUpper ();
+ verbatimID = value;
}
}
str = str.Substring (2).Trim ();
int len = str.Length;
int lastQuote = str.LastIndexOf ('"');
- if (len < 10 || lastQuote != len - 1 || !str.StartsWith ("#include "))
+ if (len < 10 || lastQuote != len - 1)
+ return false;
+
+ if (!StrUtils.StartsWith (str, "#include ", true))
return false;
str = str.Substring (9).Trim ();
- bool isfile = (str.StartsWith ("file"));
- if (!isfile && !str.StartsWith ("virtual"))
+ bool isfile = (StrUtils.StartsWith (str ,"file", true));
+ if (!isfile && !StrUtils.StartsWith (str, "virtual", true))
return false;
pathType = (isfile) ? "file" : "virtual";
int index = 1;
for (; index < str.Length; index++) {
if (Char.IsWhiteSpace (str [index]))
- index++;
+ continue;
else if (str [index] == '"')
break;
}
}
tagtype = TagType.Tag;
- if (Eat ('/') && Eat ('>'))
+ if (Eat ('/') && Eat ('>')) {
tagtype = TagType.SelfClosing;
- else if (!Eat ('>'))
- OnError ("expecting '>'. Got '" + tokenizer.Value + "'");
+ } else if (!Eat ('>')) {
+ if (attributes.IsRunAtServer ()) {
+ OnError ("The server tag is not well formed.");
+ break;
+ }
+ tokenizer.Verbatim = true;
+ attributes.Add ("", GetVerbatim (tokenizer.get_token (), ">") + ">");
+ tokenizer.Verbatim = false;
+ }
}
break;
int token;
TagAttributes attributes;
string id;
+ bool wellFormedForServer = true;
attributes = new TagAttributes ();
while ((token = tokenizer.get_token ()) != Token.EOF){
+ if (token == '<' && Eat ('%')) {
+ tokenizer.Verbatim = true;
+ attributes.Add ("", "<%" +
+ GetVerbatim (tokenizer.get_token (), "%>") + "%>");
+ tokenizer.Verbatim = false;
+ tokenizer.InTag = true;
+ continue;
+ }
+
if (token != Token.IDENTIFIER)
break;
+
id = tokenizer.Value;
if (Eat ('=')){
if (Eat (Token.ATTVALUE)){
attributes.Add (id, tokenizer.Value);
+ wellFormedForServer &= tokenizer.AlternatingQuotes;
} else if (Eat ('<') && Eat ('%')) {
- attributes.Add (id, "<%" +
- GetVerbatim (tokenizer.get_token (), "%>"));
+ tokenizer.Verbatim = true;
+ attributes.Add (id, "<%" +
+ GetVerbatim (tokenizer.get_token (), "%>") + "%>");
+ tokenizer.Verbatim = false;
+ tokenizer.InTag = true;
} else {
OnError ("expected ATTVALUE");
return null;
}
-
} else {
attributes.Add (id, null);
}
}
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){
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;
}
token = tokenizer.get_token ();
}
+ if (token == Token.EOF)
+ OnError ("Expecting " + end + " and got EOF.");
+
return RemoveComments (vb_text.ToString ());
}
void GetServerTag (out TagType tagtype, out string id, out TagAttributes attributes)
{
string inside_tags;
+ bool old = tokenizer.ExpectAttrValue;
+ tokenizer.ExpectAttrValue = false;
if (Eat ('@')){
+ tokenizer.ExpectAttrValue = old;
tagtype = TagType.Directive;
id = "";
if (Eat (Token.DIRECTIVE))
}
if (Eat (Token.DOUBLEDASH)) {
+ tokenizer.ExpectAttrValue = old;
tokenizer.Verbatim = true;
inside_tags = GetVerbatim (tokenizer.get_token (), "--%>");
tokenizer.Verbatim = false;
return;
}
+ tokenizer.ExpectAttrValue = old;
bool varname;
bool databinding;
varname = Eat ('=');
(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);
}
}