html code opschonen van tags en classes
ik ben laatste uur even bezig geweest om geposte html te parsen naar iets wat veiliger is voor .. mezelf.
Ik heb geprobeer om eigenlijk als eerste dom document->validate() te doen, maar dat duurde zoo lang, en dan falen op 'external' gedoe waar ik ook al niet uitkwam, als iemand weet hoe ik da kan fixen ook graag :D
Ik heb een set aan html elementen, en classnames die ik wel wil toelaten.
Wat vinden jullie hiervan?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$allowedTags = '<tr><td><i><span>';
$allowedClasses = array('fa','fa-exclamation','fa-questionmark','tooltip');
$foundClasses = false;
$cleanHtml = strip_tags($html,$allowedTags);
preg_match_all('/class[ \t]*=[ \t]*"[^"]+"/',$cleanHtml,$foundClasses);
if(is_array($foundClasses)) {
foreach($foundClasses[0] as $cClass) {
$finalClass = $cClass;
$tClass = str_replace('class=','',str_replace('"','',$cClass));
$eClass = explode(' ',$tClass);
$returnClass = '';
foreach($eClass as $sClass) {
if(in_array($sClass, $allowedClasses)) {
if($returnClass !== '') { $returnClass .= ' '; }
$returnClass .= $sClass;
}
}
if(strlen($returnClass) > 0) {
$returnClass = 'class="' . $returnClass . '"';
}
$cleanHtml = str_replace($cClass,$returnClass,$cleanHtml);
}
}
$allowedClasses = array('fa','fa-exclamation','fa-questionmark','tooltip');
$foundClasses = false;
$cleanHtml = strip_tags($html,$allowedTags);
preg_match_all('/class[ \t]*=[ \t]*"[^"]+"/',$cleanHtml,$foundClasses);
if(is_array($foundClasses)) {
foreach($foundClasses[0] as $cClass) {
$finalClass = $cClass;
$tClass = str_replace('class=','',str_replace('"','',$cClass));
$eClass = explode(' ',$tClass);
$returnClass = '';
foreach($eClass as $sClass) {
if(in_array($sClass, $allowedClasses)) {
if($returnClass !== '') { $returnClass .= ' '; }
$returnClass .= $sClass;
}
}
if(strlen($returnClass) > 0) {
$returnClass = 'class="' . $returnClass . '"';
}
$cleanHtml = str_replace($cClass,$returnClass,$cleanHtml);
}
}
p.s. heb er nog geen functie van gemaakt of geheel ingekort.
Dat wil ik pas doen als ik helemaal klaar ben en het werkt naar behoren en is geoptimaliseerd.
Gewijzigd op 31/05/2018 23:37:40 door Dennis WhoCares
In je eerste match (doe maar een print_r($foundClasses); ) zitten dan alleen de classes. Met preg_split() kun je die dan "exploderen" op whitespace (dat is "\s", volgens mij kan dat net zo goed als steeds "[ \t]"). Met array_intersect() houd je dit lijstje dan tegen je $allowedClasses. Vervolgens implode() je de het resultaat weer voor je $cleanHtml (zelf nog even "class=" + quotes d'r bij plakken).
Ik zou je regex aanpassen naar:Ik ben nog niet zo heel goed met regex.
Door je [^"] krijg ik nu in mn regex result
[0] t gehele resultaat zoals ik al had, [1] alles wat binnen de "" valt.
Cool!
Die kan ik valideren en de regel van [0] vervangen (met class="" uiteraard)
Snap alleen niet goed wat je bedoel met intersect enz.
Zal daar komende tijd eens meer in verdiepen :)
Graag zou ik ook de dom->validate() werkend willen hebben.
Door een wizard dat heel behoorlijk dynamisch is, maak ik tabel regels. Die ik hiermee dus valideer en bijwerk waar nodig.
Als ik van tevoren al weet dat de markup al niet goed is, kan ik daar dan al niet meer in de fout gaan.
Thanks!
Gewijzigd op 01/06/2018 19:58:27 door Dennis WhoCares
Die [^"] had je zelf al in je regex staan. Dat betekent gewoon 'alles behalve "'. Dus je zoekt vanaf een " 'alles behalve een "' (en dan weer een "). Doordat je d'r (...) omheen zet ga je dat stukje "groeperen", en krijg je 'm apart terug. Dan hoef je niet zelf te knutselen (jouw regel 11).
Overigens kan een attribuut-waarde ook met single-quotes omsloten worden. Die glippen d'r nu gewoon tussendoor. En als het slechts een enkele class is (geen spaties) kan het ook zonder quotes. Merk op dat dit een behoorlijk "gevecht" kan zijn met je "gebruikers": https://en.wikipedia.org/wiki/Samy_%28computer_worm%29
Met een intersect krijg je alleen de waarden die in beide arrays voorkomen. Als je dus een lijstje met class names hebt, en je intersect die met de $allowedClasses, dan hou je van het originele lijstje alleen diegene over die "allowed" zijn.
Samenvattend:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
//ik pak de voorloop-spaties voor de "class" ook mee, zodat die ook verdwijnen als er geen class names overblijven
//tevens PREG_SET_ORDER, dan houd je alles in een setje compleet
//en ik check dus voor single-quotes, double-quotes, of (| teken) geen quotes
if(preg_match_all('/\\s+class\\s*=\\s*(\'([^\']*)\'|"([^"]*)"|(\\w+))/',$cleanHtml,$foundClasses,PREG_SET_ORDER))
foreach($foundClasses as $cClass){
$full = $cClass[0]; //full match (dus incl. class="...")
$eClass = preg_split('/\s+/',array_pop($cClass)); //array met class names
$returnClass = implode(' ',array_intersect($eClass,$allowedClasses)); //alleen de toegestane class names
if(strlen($returnClass) > 0) {
$returnClass = ' class="' . $returnClass . '"'; //let op: hier weer een extra spatie voor "class"
}
$cleanHtml = str_replace($full,$returnClass,$cleanHtml);
}
//tevens PREG_SET_ORDER, dan houd je alles in een setje compleet
//en ik check dus voor single-quotes, double-quotes, of (| teken) geen quotes
if(preg_match_all('/\\s+class\\s*=\\s*(\'([^\']*)\'|"([^"]*)"|(\\w+))/',$cleanHtml,$foundClasses,PREG_SET_ORDER))
foreach($foundClasses as $cClass){
$full = $cClass[0]; //full match (dus incl. class="...")
$eClass = preg_split('/\s+/',array_pop($cClass)); //array met class names
$returnClass = implode(' ',array_intersect($eClass,$allowedClasses)); //alleen de toegestane class names
if(strlen($returnClass) > 0) {
$returnClass = ' class="' . $returnClass . '"'; //let op: hier weer een extra spatie voor "class"
}
$cleanHtml = str_replace($full,$returnClass,$cleanHtml);
}
Ik snap het helemaal het is gelukt :D bedankt voor de jip janeke :-)
Ik ga ook alles wat niet geen class attribute is weggooien uit de html :)
Heb die link idd vaker gezien
Tijd voor vakantie!
Gewijzigd op 02/06/2018 08:55:38 door Dennis WhoCares
liep ik hier toevalling tegenaan. Misschien enigszins gedateerd, maar zeker nog relevant. Geeft je misschien wat ideeën.
Huh, compleet ongerelateerd aan dit topic je hebt helemaal gelijk. We zullen ook eerst alle ascii hex en urlsafe characters moeten converteren naar normale karakters en vervolgrns deze 'filter' eroverheen te halen.
Na de vakantie ga ik me hier eens in verdiepen. Ik wil namelijk niet simpelweg %, ; etc willen strippen, omdat dit zeker wel acceptabele karakters zijn als input van de gebruikers.