Mastershrimp: Selbstgebautes htmlentities() scheitert an Sonderzeichen + UTF-8

Beitrag lesen

Heyho!

Zugegeben, ein etwas spezielleres Thema. Vielleicht denke ich auch einfach zu kompliziert. Ich erklärs mal in Ruhe:

  1. Ziel:
    Ich habe ein Formular, das den WYSIWYG-Editor "TinyMCE" einsetzt. In dieses Feld soll man beliebige Zeichen (auch Sonderzeichen wie das Pik/Karo/Herz-Zeichen und Umlaute) eintragen können. Diese landen beim Abspeichern in der Datenbank. Dort finde ich, sollten sie nicht maskiert landen, weil man sonst Probleme bekommt, wenn man nach DB-Inhalten sucht (macht Sinn, oder?).
    Also habe ich TinyMCE so eingestellt, dass es nix maskiert und den Inhalt einfach so an die DB weiterreicht. Funktioniert super.

Der Haken ist halt nun, dass bei der Ausgabe des Inhalts dieser maskiert werden muss. Hierfür habe ich zum einen die standardmäßige htmlentities(), die ja dank des letzten Parameters auch wunderbar mit UTF-8 umgehen kann. Für 90% meiner Inhalte reicht das auch.

Eine Ausnahme stellen TinyMCE-Inhalte dar, da diese ja HTML enthalten, was ja bei htmlentities() dann ebenfalls maskiert werden würde. Daher entschied ich mich, eine eigene Methode (quasi "htmlentitiesHTML()" ;-) ) zu bauen, die im wesentlichen wie htmlentities() funktioniert, ohne < > " ' zu maskieren. Dazu noch ein strip_tags() um böse Tags herauszuhauen und fertig.

In der Theorie super, in der Praxis scheitert's leider :/

  1. Problem:
    Hier mein erster Ansatz:
  
// --- Encode  
// Perform all actions of htmlentities() except replacing some special characters (see below)  
// FIXME  
// Convert temporarily  
$content = iconv("UTF-8", "ISO-8859-1", $content);  
  
// Remove html tags which are not allowed  
$content = strip_tags($content, ALLOWED_HTML);  
  
// Create $search and $replace, without the following characters: > < " ' and blanks  
$htmlentitiesTable = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);  
$search = array("&");		// Note: "&" is already in this array because all "&" need to be replaced at first! Otherwise the tags would be double-encoded  
$replace = array("&amp;");  
foreach($htmlentitiesTable as $key => $value) {  
	if($key!="<" && $key!=">" && $key!=" " && $key!="" && $key!="&") {  
		$search[]	= $key;  
		$replace[]	= $value;  
	}  
}  
$content = str_replace($search, $replace, $content);  
  
// Convert back to UTF8  
$content = iconv("ISO-8859-1", "UTF-8", $content);  
  
return $content;  

Ich konvertiere also zuerst den String in einen Zeichensatz, den PHP bedienen kann, mache die gewohnten String-Operationen und konvertiere anschließend zurück. Dummerweise wird der String vor dem ersten Sonderzeichen abgeschnitten. Irgendwo in der Docu stand, dass PHP das macht, wenn es ein Zeichen findet, das für den aktuellen Zeichensatz nicht gültig ist.
Lustigerweise werden Umlaute korrekt maskiert. Lediglich Sonderzeichen wie Karo/Pik/Herz oder das Unendlich-Zeichen zwingen die Funktion zum Abbruch.

Wenn ich statt "ISO-8859-1" "ASCII" nehme, bricht die Funktion auch bei Umlauten ab.

Und hier noch ein zweiter:

  
// Create $search and $replace, without the following characters: > < " ' and blanks  
$htmlentitiesTable = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);  
$search = array("&");		// Note: "&" is already in this array because all "&" need to be replaced at first! Otherwise the tags would be double-encoded  
$replace = array("&amp;");  
foreach($htmlentitiesTable as $key => $value) {  
	if($key!="<" && $key!=">" && $key!=" " && $key!="" && $key!="&") {  
		$search[]	= $key;  
		$replace[]	= $value;  
	}  
}  
  
mb_regex_encoding("UTF-8");  
for($i=0; $i<count($search); $i++)  
	$content = mb_ereg_replace($search[$i], $replace[$i], $content);  
  
return $content;  

Ergebnis: Nix wird maskiert. Der Inhalt wird einfach unmaskiert ausgegeben.

Ich hoffe ich hab euch jetzt mit dieser ausführlichen Beschreibung nicht erschlagen ;-)
Habt ihr ne Idee wie ich das Problem lösen könnte? Mir gehen langsam die Ideen aus....

Achja, vielleicht sollte ich noch erwähnen dass alle Dateien natürlich in UTF-8 gespeichert sind und auch sonst alles (Header, DB-Connection, ...) auf "UTF-8" steht. Die Ausgabe mit htmlentities() klappt ja auch soweit.

Viele Grüße

Mastershrimp