Web-TorMedlem sedan nov. 200013 890 inlägg 1. Jag använda följande kod för få min sida validerad som XHTML:
/*
* Written by Mark Pasternak, [email]mark.pasternak@universum.se[/email]
* Feel free to modify
*/
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace Consolidate
{
/// <summary>
/// Response Filter that modifies the ASP.NET output so it can validate against the XHTML 1.1 Strict standard.
/// Two things are modified:
/// 1. The form name attribute is removed. Warning, this may break JavaScript code!
/// 2. The viewstate is wrapped in a div element.
/// </summary>
public class XHTMLStrictFilter : Stream
{
private Stream _sink;
private long _position;
private static Regex _regForm = new Regex([b][red]"<form .*name=.* .*>"[/red][/b], RegexOptions.Compiled|RegexOptions.IgnoreCase);
private static Regex _regNameReplace = new Regex("name=[^ ]*", RegexOptions.Compiled|RegexOptions.IgnoreCase);
private static Regex _regViewState = new Regex("<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", RegexOptions.Compiled|RegexOptions.IgnoreCase);
private bool _formFix;
private bool _viewStateFix;
public XHTMLStrictFilter(Stream sink)
{
_sink = sink;
}
// The following members of Stream must be overriden.
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { return 0; }
}
public override long Position
{
get { return _position; }
set { _position = value; }
}
public override long Seek(long offset, System.IO.SeekOrigin direction)
{
return _sink.Seek(offset, direction);
}
public override void SetLength(long length)
{
_sink.SetLength(length);
}
public override void Close()
{
_sink.Close();
}
public override void Flush()
{
_sink.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
// The Write method actually does the filtering.
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data;
if(!_formFix || !_viewStateFix)
{
string htmlOutput = System.Text.UTF8Encoding.UTF8.GetString(buffer);
int length = htmlOutput.Length;
if(!_formFix && _regForm.IsMatch(htmlOutput))
{
string formMatch=_regForm.Match(htmlOutput).Value;
htmlOutput=Regex.Replace(htmlOutput, formMatch, _regNameReplace.Replace(formMatch, ""), RegexOptions.IgnoreCase);
_formFix=true;
}
if(!_viewStateFix && _regViewState.IsMatch(htmlOutput))
{
string viewStateMatch=_regViewState.Match(htmlOutput).Value;
htmlOutput=Regex.Replace(htmlOutput, viewStateMatch, "<div>"+viewStateMatch+"</div>", RegexOptions.IgnoreCase);
_viewStateFix=true;
}
data = System.Text.UTF8Encoding.UTF8.GetBytes(htmlOutput);
count -= length - htmlOutput.Length;
}
else
{
data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
}
_sink.Write(data, 0, count);
}
}
}
Den ska bl.a. ta bort name="foo" ur alla form-taggar. Problemet är att det inte funkar om action-attributet innehåller ett frågetecken:
<!-- Funkar -->
<form name="foo" action="test.html">
<!-- Funkar inte -->
<form name="foo" action="test.html?var=1">
Hur kan man lösa det?
2. Vad jag förstår går det att lägga till ovanstående klass i global.asax så att alla sidor körs genom XHTML-filtrer. Hur gör jag det?
Web-TorMedlem sedan nov. 200013 890 inlägg Ok! Jag vet att det är en rejäl bit kod men någon borde väl vara duktigt på Regex. :q
Problemet borde väl ligga i den fetmarkerade biten ovanför?
icaaqMedlem sedan okt. 20005 273 inlägg 1.
[red]
private static Regex _regForm = new Regex("<form .*name=\".*\">", RegexOptions.Compiled|RegexOptions.IgnoreCase);
[/red]
2.
[red]
protected void Application_EndRequest(Object sender, EventArgs e)
{
Response.Filter = new XHTMLStrictFilter(Response.Filter);
}[/red]
helt otestat ;)
Web-TorMedlem sedan nov. 200013 890 inlägg 1. Ingen skillnad. :(
2. /r Det funkade om jag lade den i Application_BeginRequest. :)
Web-TorMedlem sedan nov. 200013 890 inlägg Jag ställer väl frågan på ett annat sätt då:
Hur gör jag för att matcha name="" när det ligger i form-tagg?
Web-TorMedlem sedan nov. 200013 890 inlägg Ingen som kan något om reguljära uttryck alltså?
DavidBMedlem sedan jan. 20001 372 inlägg spangoMedlem sedan juni 20008 205 inlägg Alltså... nu kan ju inte jag C#, men jag gör ett försök ändå. Jag tror att regexpen i sin nuvarande form kan vara något för girig, om det ser ut så här:
@"<form .*name=(.).*?\1 .*>"
skulle det kanske funka. :OO
Web-TorMedlem sedan nov. 200013 890 inlägg Det var inte fel på min RegEx överhuvudtaget.
Jag fick hjälp på ett annat forum :r och svaret låg i den här raden.
// Gammal och fel
htmlOutput=Regex.Replace(htmlOutput, formMatch, _regNameReplace.Replace(formMatch, "")
// Ny och rätt
htmlOutput=Regex.Replace(htmlOutput,_regNameReplace.Match(formMatch).value,"")
Inte för att jag fattar varför men nu funkar det. :)
Web-TorMedlem sedan nov. 200013 890 inlägg Jag har hittat ett fel till. :(
Den här gången är det div-taggarna runt ViewState som inte funkar om ViewState-fältet innehåller ett plus (+).
Funkar
<input type="hidden" name="__VIEWSTATE" value="dDwtMTE5MjY4" />
Funkar inte
<input type="hidden" name="__VIEWSTATE" value="**+**dDwtMTE5MjY4" />
Snälla, hjälp!
Web-TorMedlem sedan nov. 200013 890 inlägg Nu har hag fått hjälp att lösa detta och felet var att alla RegEx-tecken (+, ?, \, ^, m.m.) tolkades som just RegEx.
// Fel
htmlOutput=Regex.Replace(htmlOutput, viewStateMatch, "<div>"+viewStateMatch+"</div>");
// Rätt
htmlOutput=Regex.Replace(htmlOutput, "<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", "<div>"+viewStateMatch+"</div>");
Det kan vara bra att veta för alla andra som använder det här filtret. ;)
icaaqMedlem sedan okt. 20005 273 inlägg Jag skulle vilja kicka igång denna tråd igen och undrar om man kan ta bort alla border="0" genom detta filter.
någon med stora regEx kunskaper kanske kan ge mig ett filter som funkar ;)
mv icaaq
icaaqMedlem sedan okt. 20005 273 inlägg Fixade det själv :)
[red]
/*
* Written by Mark Pasternak, [email]mark.pasternak@universum.se[/email]
* Feel free to modify
*/
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace NineteenDecember
{
/// <summary>
/// Response Filter that modifies the ASP.NET output so it can validate against the XHTML 1.1 Strict standard.
/// Two things are modified:
/// 1. The form name attribute is removed. Warning, this may break JavaScript code!
/// 2. The viewstate is wrapped in a div element.
/// </summary>
public class XHTMLStrictFilter : Stream
{
private Stream _sink;
private long _position;
private static Regex _regForm = new Regex("<form .*name=.* .*>", RegexOptions.Compiled|RegexOptions.IgnoreCase);
private static Regex _regNameReplace = new Regex("name=[^ ]*", RegexOptions.Compiled|RegexOptions.IgnoreCase);
private static Regex _regViewState = new Regex("<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", RegexOptions.Compiled|RegexOptions.IgnoreCase);
// Tillagd 2004-02-11. Tar bort alla border="0"
private static Regex _regBorder = new Regex("border=[^ ]*", RegexOptions.Compiled|RegexOptions.IgnoreCase);
private bool _formFix;
private bool _viewStateFix;
private bool _borderFix;
public XHTMLStrictFilter(Stream sink)
{
_sink = sink;
}
// The following members of Stream must be overriden.
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { return 0; }
}
public override long Position
{
get { return _position; }
set { _position = value; }
}
public override long Seek(long offset, System.IO.SeekOrigin direction)
{
return _sink.Seek(offset, direction);
}
public override void SetLength(long length)
{
_sink.SetLength(length);
}
public override void Close()
{
_sink.Close();
}
public override void Flush()
{
_sink.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
// The Write method actually does the filtering.
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data;
if(!_formFix || !_viewStateFix || !_borderFix)
{
//string htmlOutput = System.Text.UTF8Encoding.UTF8.GetString(buffer);
string htmlOutput = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(buffer);
int length = htmlOutput.Length;
if(!_formFix && _regForm.IsMatch(htmlOutput))
{
string formMatch=_regForm.Match(htmlOutput).Value;
// *** Borttagen 03-06-17 ***
// *** htmlOutput=Regex.Replace(htmlOutput, formMatch, _regNameReplace.Replace(formMatch, ""), RegexOptions.IgnoreCase);
htmlOutput=Regex.Replace(htmlOutput, _regNameReplace.Match(formMatch).Value,"", RegexOptions.IgnoreCase);
_formFix=true;
}
if(!_viewStateFix && _regViewState.IsMatch(htmlOutput))
{
string viewStateMatch=_regViewState.Match(htmlOutput).Value;
htmlOutput=Regex.Replace(htmlOutput, "<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", "<div>"+viewStateMatch+"</div>", RegexOptions.IgnoreCase);
_viewStateFix=true;
}
// Tillagd 2004-02-11. Tar bort alla border="0"
if(!_borderFix && _regBorder.IsMatch(htmlOutput))
{
string formMatch=_regBorder.Match(htmlOutput).Value;
htmlOutput=Regex.Replace(htmlOutput, _regBorder.Match(formMatch).Value,"", RegexOptions.IgnoreCase);
_borderFix=true;
}
//data = System.Text.UTF8Encoding.UTF8.GetBytes(htmlOutput);
data = System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(htmlOutput);
count -= length - htmlOutput.Length;
}
else
{
data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
}
_sink.Write(data, 0, count);
}
}
}
[/red]
Det kan vara bra att veta för alla andra som använder det här filtret. ;)
mv icaaq
maqeMedlem sedan dec. 2003824 inlägg Använder det filtret som finns i den senaste tråden men jag får endå fel på hidden taggarna för viewstate <input type="hidden" name="__EVENTTARGET" value="" /> samt <script language="javascript" type="text/javascript"> ... Är inte det filtret komplett?
maqeMedlem sedan dec. 2003824 inlägg __EVENTTAGET och __EVENTARGUMENT fick jag lägga till i koden bara men 2 language="javascript" skulle jag även vilja ta bort ... man får väl göra en regexp för det med antar jag?
maqeMedlem sedan dec. 2003824 inlägg Verkar som att __dopostback funktionen har både languge och type? <script language="javascript" type="text/javascript"> Är det ingen som använder detta filter längre och har en nyare version. Jag löste javascript felet i __doPostBack genom att ta bort language attributet men det är ju inte så vettigt kanske...
Web-TorMedlem sedan nov. 200013 890 inlägg Poängen med scriptet är ju att få sidan att validera enligt XHTML standarden. Då kan du ju ta bort language-attributet. ;)
maqeMedlem sedan dec. 2003824 inlägg Näe jag vet det men eftersom __doPostBack innehåller både language och type så var jag tvungen att ta bort language för att endast får type kvar :) ... förstår inte varför min __doPostBack function innehåller både language och type ... kanske för att jag kör episerver?
maqeMedlem sedan dec. 2003824 inlägg Verkar som att man får ersätta __dopostback på något sätt ... nån som vet hur?
maqeMedlem sedan dec. 2003824 inlägg Nu verkar jag ha fått allt att fungera förutom att jag måste ha name attributet i formuläret. När jag plockar bort name attributet i form taggen och bara har id så smäller __dopostback funktionen med felet att __EVENTTARGET är null eller inget objekt. Skulle vara otroligt tacksam om nåon som själv kör detta kunde vara lite hjälpsam.