html code opschonen van tags en classes

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Dennis WhoCares

Dennis WhoCares

31/05/2018 23:26:30
Quote Anchor link
Dag allemaal,

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)
PHP script in nieuw venster Selecteer het PHP script
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
$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);
    }
}

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
 
PHP hulp

PHP hulp

05/02/2023 05:31:46
 
Rob Doemaarwat

Rob Doemaarwat

01/06/2018 06:33:38
Quote Anchor link
Ik zou je regex aanpassen naar:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
preg_match_all('/class[ \t]*=[ \t]*"([^"]+)"/',$cleanHtml,$foundClasses);
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).
 
Dennis WhoCares

Dennis WhoCares

01/06/2018 19:55:01
Quote Anchor link
Hi rob,

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
 
Rob Doemaarwat

Rob Doemaarwat

01/06/2018 21:41:40
Quote Anchor link
Ok, nog even in slow-motion. Ik had vanmorgen een beetje haast ;-)

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)
PHP script in nieuw venster Selecteer het PHP script
1
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);
  }
 
Dennis WhoCares

Dennis WhoCares

02/06/2018 08:55:15
Quote Anchor link
Awesome Rob!
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
 
Thomas van den Heuvel

Thomas van den Heuvel

03/06/2018 15:01:28
Quote Anchor link
Huh, compleet ongerelateerd aan dit topic liep ik hier toevalling tegenaan. Misschien enigszins gedateerd, maar zeker nog relevant. Geeft je misschien wat ideeën.
 
Dennis WhoCares

Dennis WhoCares

08/06/2018 11:32:33
Quote Anchor link
Hi Thomas,

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.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.