WordPress Dashboard Feeds mit fehlerhaften Umlauten
codestyling | 14. September 2008 | 17:06
Immer mal wieder tauchen diese komischen Zeichen in den Texten der importierten Feeds auf. Wenn es der private, eigene Blog ist, könnte man ja noch darüber hinweg sehen. Spätestens bei Blogs, die Auftragsarbeiten sind und die Kunden ihre eigenen Feeds konfigurieren wollen, stellt dies ein ernst zu nehmendes Problem dar.
Der Fehler liegt wieder mal im Detail und ist abhängig von der verwendeten PHP Version und der Kodierung des zu importierenden Feeds.
Um es vorweg zu nehmen, es gibt auch Installationen, auf denen dieses Problem nicht sofort oder augenscheinlich hervortritt. Damit jeder eine Vorstellung davon hat, was genau gemeint ist, hier nochmal zwei Screenshots des Dashboard. Als Beispiele wurden die Feeds des Blogs von WordPress Deutschland (UTF-8) und einer Internet-Zeitung (ISO-8859-1) gewählt.
Wie man daran erkennen kann, ist es nicht gerade ein rühmlicher Eindruck, den man dabei bekommt. Aber woher kommen diese Probleme und warum stellen andere Feed-Reader das korrekt dar?
Die Antwort darauf ist einfach: Feed-Reader Programme haben viel mehr “Intelligenz” verpasst bekommen, um mit gemischten oder fehlerhaften Feed immer noch so weit wie möglich umgehen zu können. Auch die Erkennung der Inhaltskodierung ist deutlich fortschrittlicher, als das die PHP Komponenten von WordPress machen.
WordPress selbst benutzt eine Implementierung von MagpieRSS um Feeds einerseits zu analysieren und andererseits in der Datenbank zu speichern, damit der Inhalt nicht bei jedem Seitenaufruf geladen wird sondern nur in konfigurierbaren Intervallen. Innerhalb des Intervalls wird der Feedinhalt direkt aus der Datenbank geladen und angezeigt.
Hier zeigt sich ein weiteres Problem. Denn die Umstellung auf einen anderen Feed im Dashboard setzt nicht unbedingt den Zeitstempel zurück. Deshalb bekommt man unter Umständen einen veralteten Feed zu sehen, weil dieser vorher mal aktiv war. Ausserdem kann es passieren, das Feedinhalte, die fehlerhaft verarbeitet und gespeichert wurden, nicht wieder korrekt ausgelesen werden können und sogar WordPress daran hindern, den Feed je wieder neu abzuholen.
Für die Mehrzahl der genannte Probleme habe ich eine Lösung gefunden. Die hier gezeigten und ggf. zum Download bereitgestellten Patches sind unter folgenden Bedingungen getestet worden:
WordPress: 2.5.0 | 2.5.1 | 2.6.0 | 2.6.1 | 2.6.2
PHP: 4.4.2 - 4.4.8 | 5.0 und höher
Folgende Datei wurde dabei modifiziert: /wp-includes/rss.php
encoding - oder wie erkenne ich den Feedinhalt richtig
In der verwendeten Klasse wird dies hier im Konstruktor aufgerufen:
$parser = @xml_parser_create();
Laut Beschreibung im PHP Manual sollte der erzeugte Parser die Kodierung des Feeds selbst erkennen, wenn man nichts als Parameter mitgibt. Das ist nur die halbe Wahrheit. PHP5 erkennt sehr wohl die Feedkodierung nicht jedoch PHP4. Wer noch einen auf PHP4 Basis betriebenen Blog hat, steht nun vor dem Problem, dass die Erkennung auf den BOM Marker ausgerichtet ist, um UTF-8 kodierte Feeds zu erkennen. Fehlt dieser (was üblich ist), dann ist für PHP4 dieser Feed automatisch ISO-8859-1 kodiert, ein schwerer Fehler!
Um dem Abhilfe zu schaffen, analysiert man den Feed-Rohinhalt einfach selbst nach der Kodierung. Dem entsprechend hab ich den Code erweitert und per Regular Expression die Eingangskodierung ermittelt:
preg_match('/<\?xml\s*version="1.0"\s*encoding="(UTF-8|ISO-\d+-\d+)"\s*\?>/', $source, $hits); //detect the feeds encdoding, while PHP4 detection doesn't work!
$parser = @xml_parser_create($hits[1]); //initialize proper input encoding
@xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, get_option('blog_charset')); //initialize proper output encoding, dependend on blogs setting
Für alle PHP Versionen wird nun die Eingangskodierung ermittelt und gesetzt (auch wenn es für PHP5 nicht nötig wäre). Und es wird die Ausgangskodierung festgelegt gemäß der Einstellung des Blogs, welche vorher gänzlich fehlte.
Da wir an anderer Stelle im Code nochmal eine “Sonderwurst” für PHP5 machen müssen, dies dort aber mehrfach aufgerufen wird, ermitteln wir noch schnell, ob es sich um eine PHP >= 5.0 Version handelt:
$this->is_php5 = version_compare(phpversion(), "5.0", '>='); //detect php 5 for later use of qualified html entity conversion
Jetzt sollte bereits für PHP 4 Versionen der Feed vollkommen korrekt erkannt, gespeichert und angezeigt werden. Jedoch fehlt noch eine Kleinigkeit in einer Methode, die nur bei PHP5 nötig ist:
function append($el, $text) {
if (!$el) {
return;
}
if ($this->is_php5) $text = @html_entity_decode($text, ENT_QUOTES, get_option('blog_charset')); //PHP 5 only !!!
if ( $this->current_namespace )
Die HTML-Entities müssen bei PHP5 an den Charset des Blogs angepasst werden, sonst hat man keine vernünftige Darstellung der Umlaute.
Dies waren nun auch schon alle Änderungen, die vorgenommen werden müssen. Nun können Feeds immer korrekt angezeigt und gespeichert werden, völlig unabhängig, welche Kodierung oder PHP Version zugrunde liegt.
Feed ist nicht vorhanden - oder wieso geht jetzt nichts mehr?
Wenn man die Feeds umkonfiguriert, kann es passieren, dass danach das Dashboard sie nicht mehr kennen will. Das liegt daran, das MagpieRSS die Datenbank als Cache benutzt und in der Tabelle wp_options die Feedinhalte zwischenspeichert.
Es kann vorkommen, das kaputte Serialisierungen der vorherigen, fehlerhaften Datei gespeichert wurden. Diese können nicht mehr eingelesen werden und der Feed wird nie wieder angezeigt.
Dies kann man lösen, wenn man in der Datenbank alle gespeicherten Feedinhalte von MagpieRSS entfernt. Dazu öffnet man per phpMyAdmin die Tabelle wp_options und sucht alle Einträge dieser Art raus:
option_name: rss_7636fcd12af6751344b6ab1541a834fb
option_name: rss_7636fcd12af6751344b6ab1541a834fb_ts
Alles, was zu MagpieRSS gehört, beginnt mit rss_ gefolgt von der MD5 Kennung des Feeds. Die Einträge, die hinten dran noch _ts haben, sind der Zeitstempel der letzten Aktualisierung.
Alle diese Einträge können gelöscht werden, denn sie werden neu erzeugt, wenn der Feed irgendwo angezeigt werden soll. Somit kann man sicherstellen, dass die Datenbank nach dem Einspielen des Patches immer korrekte Daten enthält und keine kaputten Feedinhalte die Darstellung verhindern.
Patch der Datei /wp-includes/rss.php: rss.zip (192 downloads)
(ist anwendbar auf allen WordPress Versionen >= 2.5.1)
Ich werde die Meldung im WordPress Bug-Trac Ticket #7563 mit diesem Patch noch erweitern in der Hoffnung, das dies in einer der nächsten offiziellen Versionen fester Bestandteil wird.








Pascal
14.09.2008 | 18:16Vielen Dank, dass du dies publik gemacht hast. Ich habe mich schon einige Zeit daüber gewundert und war leicht genervt. Eventuell werde ich auch noch darauf verlinken
Gruss,
Pascal
Antworten »
63rd
15.09.2008 | 01:00Wow, vielen vielen Dank für diese wunderbare Lösung!
Dein Patch wurde noch nicht in v.2.6.2 implementiert, obwohl er einwandfrei funktioniert!
Hatte auch keine Probleme zwecks Datenbank-Cache.
Ich hab das Gefühl dass viele Leute nicht bis ganz nach unten Scrollen, und so auch nicht auf
den Download der gepatchten rss.php Datei treffen.
Ich hatte anfangs ehrlich gesagt auch den Eindruck es würde sich um einen Guide zum selber basteln handeln, ohne Download.
Danke und liebe Grüße aus Österreich!
Antworten »
Kretzschmar
04.03.2009 | 19:03Dein “Patch” lag nicht als svn-patch vor. Mittlerweile hat das jemand erledigt und er ist vor ein paar Tagen auch in den trunk gewandert. Bei mir klappt jetzt alles (allerdings werden die titel des rss-widgets bei mir noch immer nicht korrekt dargestellt).
Antworten »
codestyling
04.03.2009 | 19:09Vielen Dank für die Information, ich werde mir das heute später mal ansehen. Es ist durchaus möglich, dass man wieder nur die Hälfte beachtet hat und die Widgets wieder ein anderes Interface benutzen. Da es mittlerweile mehr als eine Art gibt, RSS abzuholen, befürchte ich, dass dies wieder übersehen wurde.
Eine Analyse folgt dann entweder als Update oder neuer Eintrag.
Antworten »
Jazzie
16.03.2009 | 15:51Ich habe das Problem das nach dem Update auf 2.71 gar keine Feeds mehr von einer meiner anderen Seite abgerufen werden. Hatte das schon ins Forum gepostet aber noch keine Antwort bekommen.
Zumindest bin ich froh das überhaupt noch jemand den Fehler realisiert hat. Das leeren der Caches per DB klappt aber auch nicht . Jetzt werde ich dein Script probieren.
Jazzie
Antworten »
name ere
26.04.2009 | 15:48Hab das ding ersetzt, alles beim alten! Nichts aht sich geändert. Funtktioniert micht, oder unzureichende Anleitung! Wer das hier versteht braucht vermutlich diese Anleitung nicht weil er selber weiß was zu tun ist….
Antworten »
codestyling
27.04.2009 | 11:37Abe Version 2.7 sind ein Feed Abrufe geändert worden. Es ist im Bereich der Möglichen, dass der Fix deswegen nicht greift, weil über die neuen Klassen von WP der Feed geholt wird.
Ich werde mir das nochmal ansehen und ggf. den Bugfix erneut bei WP melden, denn alle bisherigen Vorschläge und Lösungen meinerseits wurden nur halbherzig eingebaut und berücksichtigt.
Antworten »