1. Einleitung
Um HTML-Code in einem String so zu codieren, dass er vom Browser als normaler Text interpretiert wird, kann htmlentities($string, $flags, $encoding, $double_encode) verwendet werden. Die Funktion erwartet einen String als Übergabeparameter. Zudem können optional einige Flags ($flags) übergeben werden, sowie das Encoding ($encoding) des Strings (sollte in der Regel UTF-8 sein) und eine Angabe, ob bereits codierte HTML-Zeichen noch einmal codiert werden sollen ($double_encode).
Insbesondere Benutzereingaben sollten vor der Ausgabe immer mit htmlentities() codiert werden, andernfalls ergeben sich erhebliche Sicherheitslücken, da zum Beispiel Javascript-Code von außen eingeschleust werden kann.
2. Ein einfaches Beispiel
In diesem Beispiel soll eine einfache mathematische Aussage dargestellt werden. Diese enthält ein größer-als-Zeichen („>”), welches Teil der HTML-Syntax ist und daher codiert werden muss.
<?php $str = 'Daher gilt: 100 > 5. qed.'; var_dump(htmlentities($str)); ?>
string(28) "Daher gilt: 100 > 5. qed."
3. Auch einfache Anführungszeichen codieren
Standardmäßig codiert htmlentities() zwar doppelte Anführungszeichen ("), aber keine einfachen Anführungszeichen ('). In einigen Fällen kann dies ein Sicherheitsproblem sein. Um auch einfache Anführungszeichen zu codieren, muss ENT_QUOTES als zweiter Parameter hinzugefügt werden. Da man in der Regel dadurch keine Nachteile hat, ist das fast immer zu empfehlen.
Im nachfolgenden Beispiel soll eine URL eines Benutzers ausgegeben werden. Das Skript verwendet dabei falschen HTML-Code und setzt die Werte von Attributen in einfache statt doppelte Anführungszeichen. Das kann ein Angreifer ausnutzen, indem er in der auszugebenden URL ein einfaches Anführungszeichen platziert und danach eigenen HTML-Code einschleust (hier beispielsweise JavaScript).
<?php $start = "<a href='"; $end = "'>Die URL eines Benutzers</a>"; $url = "http://www.google.de/' onmouseover='alert(12345);' title='"; $code1 = $start . htmlentities($url) . $end; var_dump($code1); $code2 = $start . htmlentities($url, ENT_QUOTES) . $end; var_dump($code2); ?>
string(96) "<a href='http://www.google.de/' onmouseover='alert(12345);' title=''>Die URL eines Benutzers</a>" string(116) "<a href='http://www.google.de/' onmouseover='alert(12345);' title=''>Die URL eines Benutzers</a>"
4. Zeichensatz festlegen
Die von htmlentities() durchgeführte Codierung ist auch vom verwendeten Zeichensatz abhängig. Um Probleme zu vermeiden, sollte daher der erwartete Zeichensatz immer angegeben werden. Dieser wird in Form eines Strings (Name des Zeichensatzes) als dritter Parameter übergeben. In der Regel sollte es sich dabei um „UTF-8” handeln.
Im nächsten Beispiel wird der Zeichensatz (UTF-8) einmal weggelassen und einmal übergeben. In ersterem Fall ist das Ergebnis von htmlentities() falsch, da es die UTF-8-Zeichen nicht richtig interpretiert. Nur bei Angabe des Zeichensatzes entspricht die Rückgabe den Erwartungen.
<?php $str = 'Das ist ein ٽ<em>Beispiel</em>ٽ'; var_dump(htmlentities($str, ENT_QUOTES)); var_dump(htmlentities($str, ENT_QUOTES, 'UTF-8')); ?>
string(73) "Das ist ein Ù½<em>Beispiel</em>Ù½" string(45) "Das ist ein ٽ<em>Beispiel</em>ٽ"
5. Keine doppelten Codierungen
Kann der zu codierende String bereits codierte HTML-Zeichen enthalten, welche nicht noch einmal codiert werden sollen, dann kann (bool)false als vierter Parameter übergeben werden. Andernfalls werden diese automatisch mehrfach codiert, was zu unschönen (und falschen) Ergebnissen führen kann.
Im nachfolgenden Beispiel wird ein String übergeben, welcher einen Umlaut enthält, der bereits zuvor codiert wurde (aus „ö” wurde „ö”). Bei „normaler” Anwendung von htmlentities würde das „&” wiederum codiert werden, wodurch aus „ö” nun „&ouml;” werden würde. Das ist offensichtlich nicht gewünscht, daher wird bei der zweiten Ausgabe ein (bool)false als vierter Parameter übergeben.
<?php $str = 'Ein fröhliches Beispiel!'; var_dump(htmlentities($str, ENT_QUOTES, 'UTF-8', true)); var_dump(htmlentities($str, ENT_QUOTES, 'UTF-8', false)); ?>
string(33) "Ein fr&ouml;hliches Beispiel!" string(29) "Ein fröhliches Beispiel!"
6. Eine einheitliche htmlentities-Funktion pro Projekt
Es kann hilfreich sein, für ein Projekt oder eine Komponente eine zentrale htmlentities-Funktion zu definieren. So ist es beispielsweise möglich, den verwendeten Zeichensatz an einer zentralen Stelle festzulegen. Im Beispiel wird eine solche Funktion definiert, welche htmlentities() immer mit ENT_QUOTES als Flag und UTF-8 als Zeichensatz aufruft. Sie bietet zudem auch gleich die Möglichkeit, zu lange Strings ab einer gewissen Länge abzuschneiden (mit „...” am Ende), was im Entwicklungsalltag durchaus nützlich sein kann.
<?php function myhtmlentities($str, $maxlength=-1, $tooLongStr='...', $doubleEncode=true) { if ($maxlength>=0 && isset($str[$maxlength])) { $str = mb_substr($str, 0, $maxlength) . $tooLongStr; } return htmlentities($str, ENT_QUOTES, 'UTF-8', $doubleEncode); } $str = 'Das ist ein <em>"Beispiel"</em>'; var_dump(myhtmlentities($str)); var_dump(myhtmlentities($str, 10)); ?>
string(53) "Das ist ein <em>"Beispiel"</em>" string(13) "Das ist ei..."
7. Codierung wieder umkehren
Soll die Codierung wieder umgekehrt werden, dann kann html_entity_decode() verwendet werden
<?php $str = 'Das ist <em>HTML</em>'; $strEntities = htmlentities($str); var_dump($strEntities); var_dump(html_entity_decode($strEntities)); ?>
string(33) "Das ist <em>HTML</em>" string(21) "Das ist <em>HTML</em>"
Kommentare (1)
Von neu nach altWir bitten um ihr Verständnis.