//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Marek Habersack <mhabersack@novell.com>
//
// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2003-2009 Novell, Inc (http://novell.com)
//
//
using System.Collections;
using System.IO;
using System.Text;
+using System.Security.Cryptography;
namespace System.Web.Compilation
{
public const int EOF = 0x0200000;
public const int IDENTIFIER = 0x0200001;
public const int DIRECTIVE = 0x0200002;
- public const int ATTVALUE = 0x0200003;
+ public const int ATTVALUE = 0x0200003;
public const int TEXT = 0x0200004;
public const int DOUBLEDASH = 0x0200005;
public const int CLOSING = 0x0200006;
class AspTokenizer
{
+ const int CHECKSUM_BUF_SIZE = 8192;
+
+ class PutBackItem
+ {
+ public readonly string Value;
+ public readonly int Position;
+ public readonly int CurrentToken;
+ public readonly bool InTag;
+
+ public PutBackItem (string value, int position, int currentToken, bool inTag)
+ {
+ Value = value;
+ Position = position;
+ CurrentToken = currentToken;
+ InTag = inTag;
+ }
+ }
+
+ static char [] lfcr = new char [] { '\n', '\r' };
TextReader sr;
int current_token;
StringBuilder sb, odds;
int begcol, begline;
int position;
bool inTag;
+ bool expectAttrValue;
+ bool alternatingQuotes;
bool hasPutBack;
bool verbatim;
bool have_value;
bool have_unget;
int unget_value;
string val;
+ Stack putBackBuffer;
+ MD5 checksum;
+ char[] checksum_buf = new char [CHECKSUM_BUF_SIZE];
+ int checksum_buf_pos = -1;
+
+ public MD5 Checksum {
+ get { return checksum; }
+ }
public AspTokenizer (TextReader reader)
{
public void put_back ()
{
- if (hasPutBack)
+ if (hasPutBack && !inTag)
throw new HttpException ("put_back called twice!");
hasPutBack = true;
- position -= Value.Length;
+ if (putBackBuffer == null)
+ putBackBuffer = new Stack ();
+
+ string val = Value;
+ putBackBuffer.Push (new PutBackItem (val, position, current_token, inTag));
+ position -= val.Length;
}
public int get_token ()
{
- if (hasPutBack){
- hasPutBack = false;
- position += Value.Length;
+ if (hasPutBack) {
+ PutBackItem pbi;
+ if (verbatim) {
+ pbi = putBackBuffer.Pop () as PutBackItem;
+ string value = pbi.Value;
+ switch (value.Length) {
+ case 0:
+ // do nothing, CurrentToken will be used
+ break;
+
+ case 1:
+ pbi = new PutBackItem (String.Empty, pbi.Position, (int)value [0], false);
+ break;
+
+ default:
+ pbi = new PutBackItem (value, pbi.Position, (int)value [0], false);
+ break;
+ }
+ } else
+ pbi = putBackBuffer.Pop () as PutBackItem;
+
+ hasPutBack = putBackBuffer.Count > 0;
+ position = pbi.Position;
+ have_value = false;
+ val = null;
+ sb = new StringBuilder (pbi.Value);
+ current_token = pbi.CurrentToken;
+ inTag = pbi.InTag;
return current_token;
}
position--;
col--;
}
+
+ void TransformNextBlock (int count, bool final)
+ {
+ byte[] input = Encoding.UTF8.GetBytes (checksum_buf, 0, count);
+
+ if (checksum == null)
+ checksum = MD5.Create ();
+
+ if (final)
+ checksum.TransformFinalBlock (input, 0, input.Length);
+ else
+ checksum.TransformBlock (input, 0, input.Length, input, 0);
+ input = null;
+
+ checksum_buf_pos = -1;
+ }
+ void UpdateChecksum (int c)
+ {
+ bool final = c == -1;
+
+ if (!final) {
+ if (checksum_buf_pos + 1 >= CHECKSUM_BUF_SIZE)
+ TransformNextBlock (checksum_buf_pos + 1, false);
+ checksum_buf [++checksum_buf_pos] = (char)c;
+ } else
+ TransformNextBlock (checksum_buf_pos + 1, true);
+ }
+
int read_char ()
{
int c;
have_unget = false;
} else {
c = sr.Read ();
+ UpdateChecksum (c);
}
if (c == '\r' && sr.Peek () == '\n') {
c = sr.Read ();
+ UpdateChecksum (c);
position++;
}
int c;
int last = 0;
bool inServerTag = false;
+ alternatingQuotes = true;
while ((c = sr.Peek ()) != -1) {
if (c == '%' && last == '<') {
read_char ();
break;
}
+ } else if (quoted && c == quoteChar) {
+ alternatingQuotes = false;
}
sb.Append ((char) c);
return c;
}
- if (inTag && (c == '"' || c == '\''))
+ if (inTag && expectAttrValue && (c == '"' || c == '\''))
return ReadAttValue (c);
if (c == '<'){
}
if (inTag && current_token == '%' && "@#=".IndexOf ((char) c) != -1){
+ if (odds.Length == 0 || odds.ToString ().IndexOfAny (lfcr) < 0) {
+ sb.Append ((char) c);
+ return c;
+ }
sb.Append ((char) c);
- return c;
+ continue;
}
if (inTag && c == '-' && sr.Peek () == '-'){
get { return inTag; }
set { inTag = value; }
}
+
+ // Hack for preventing confusion with VB comments (see bug #63451)
+ public bool ExpectAttrValue {
+ get { return expectAttrValue; }
+ set { expectAttrValue = value; }
+ }
+
+ public bool AlternatingQuotes {
+ get { return alternatingQuotes; }
+ }
public int BeginLine {
get { return begline; }