Zur Navigation

RSS-Feed aus Wordpress auslesen

Script bringt mich zur Verweiflung

1 AndreasH (Gast)

Hallo Jörg,
vielleicht kannst du mir auch dieses Mal helfen! Ich verzweifel an folgendem Script ( /*-Angabe bewusst belassen!):

 <?php
/*
Nutzung dieses Scripts nur gestattet, wenn Kommentare (PHP und HTML) nicht gelöscht werden, oder ein Link zu folgender Adresse gesetzt wird:
URL: http://www.web-spirit.de/webdesign-tutorial/7/RSS-Feed-auslesen-mit-PHP
Beschreibung: RSS Feed auslesen mit PHP
Autor: Sebastian Gollus
Internet: http://www.web-spirit.de
Version: 1.0.200905
*/

// Funktionsaufruf z.B.: getRssfeed("http://www.voelklingen-im-wandel.de/nachrichten/feed","web-spirit","auto",3,3);



function getRssfeed($rssfeed, $cssclass="", $encode="auto", $anzahl=10, $mode=0)
{
    // $encode e[".*"; "no"; "auto"]

    // $mode e[0; 1; 2; 3]:
    // 0 = nur Titel und Link der Items weden ausgegeben
    // 1 = Titel und Link zum Channel werden ausgegeben
    // 2 = Titel, Link und Beschreibung der Items werden ausgegeben
    // 3 = 1 & 2
    
    // Zugriff auf den RSS Feed
    $data = @file($rssfeed);
    $data = implode ("", $data);
    if(strpos($data,"</item>") > 0)
    {
        preg_match_all("/<item.*>(.+)<\/item>/Uism", $data, $items);
        $atom = 0;
    }
    elseif(strpos($data,"</entry>") > 0)
    {
        preg_match_all("/<entry.*>(.+)<\/entry>/Uism", $data, $items);
        $atom = 1;
    }
    
    // Encodierung
    if($encode == "auto")
    {
        preg_match("/<?xml.*encoding=\"(.+)\".*?>/Uism", $data, $encodingarray);
        $encoding = $encodingarray[1];
    }
    else
    {$encoding = $encode;}
    
    echo "<!-- RSS Feed Script von Sebastian Gollus: http://www.web-spirit.de/webdesign-tutorial/7/RSS-Feed-auslesen-mit-PHP -->\n";
    echo "<div class=\"rssfeed_".$cssclass."\">\n";
    
    // Titel und Link zum Channel 
    if($mode == 1 || $mode == 3)
    {
        if(strpos($data,"</item>") > 0)
        {
            $data = preg_replace("/<item.*>(.+)<\/item>/Uism", '', $data);
        }
        else
        {
            $data = preg_replace("/<entry.*>(.+)<\/entry>/Uism", '', $data);
        }
        preg_match("/<title.*>(.+)<\/title>/Uism", $data, $channeltitle);
        if($atom == 0)
        {
            preg_match("/<link>(.+)<\/link>/Uism", $data, $channellink);
        }
        elseif($atom == 1)
        {
            preg_match("/<link.*alternate.*text\/html.*href=[\"\'](.+)[\"\'].*\/>/Uism", $data, $channellink);
        }

        $channeltitle = preg_replace('/<!\[CDATA\[(.+)\]\]>/Uism', '$1', $channeltitle);
        $channellink = preg_replace('/<!\[CDATA\[(.+)\]\]>/Uism', '$1', $channellink);

        echo "<h1><a href=\"".$channellink[1]."\" title=\"";
        if($encode != "no")
        {echo htmlentities($channeltitle[1],ENT_QUOTES,$encoding);}
        else
        {echo $channeltitle[1];}
        echo "\">";
        if($encode != "no")
        {echo htmlentities($channeltitle[1],ENT_QUOTES,$encoding);}
        else
        {echo $channeltitle[1];}
        echo "</a></h1>\n";
    }
    
    // Titel, Link und Beschreibung der Items
    foreach ($items[1] as $item) {
        preg_match("/<title.*>(.+)<\/title>/Uism", $item, $title);
        if($atom == 0)
        {
            preg_match("/<link>(.+)<\/link>/Uism", $item, $link);
        }
        elseif($atom == 1)
        {
            preg_match("/<link.*alternate.*text\/html.*href=[\"\'](.+)[\"\'].*\/>/Uism", $item, $link);
        }
        
        if($atom == 0)
        {
            preg_match("/<description>(.*)<\/description>/Uism", $item, $description);
        }
        elseif($atom == 1)
        {
            preg_match("/<summary.*>(.*)<\/summary>/Uism", $item, $description);
        }
    
        $title = preg_replace('/<!\[CDATA\[(.+)\]\]>/Uism', '$1', $title);
        $description = preg_replace('/<!\[CDATA\[(.+)\]\]>/Uism', '$1', $description);
        $link = preg_replace('/<!\[CDATA\[(.+)\]\]>/Uism', '$1', $link);
        
        echo "<p class=\"link\">\n";
        echo "<a href=\"".$link[1]."\" title=\"";
        if($encode != "no")
        {echo htmlentities($title[1],ENT_QUOTES,$encoding);}
        else
        {echo $title[1];}
        echo "\">";
        if($encode != "no")
        {echo htmlentities($title[1],ENT_QUOTES,$encoding)."</a>\n";}
        else
        {echo $title[1]."</a>\n";}
        echo "</p>\n";
        if($mode == 2 || $mode == 3 && ($description[1]!="" && $description[1]!=" "))
        {
            echo "<p class=\"description\">\n";
            if($encode != "no")
            {echo htmlentities($description[1],ENT_QUOTES,$encoding)."\n";}
            else
            {echo $description[1];}
            echo "</p>\n";
        }
        if ($anzahl-- <= 1) break;
    }
    echo "</div>\n\n";

} 

getRssfeed("http://www.voelklingen-im-wandel.de/nachrichten/feed/","test","auto",3,3);


?>

Es gibt mir aber, egal was ich versuche, nur folgendes, jeweils auf /”‘.['link'].’” verlinkt, aus:

’.['title'].’ ’.['title'].’ ’.['title'].’ ’.['title'].’

Bin ich blind/doof, oder legt sich der Feed quer?

Danke für jede Hilfe
Grüße
Andreas

24.05.2013 01:45

2 Jörg

Es gibt mir aber, egal was ich versuche, nur folgendes, jeweils auf /”‘.['link'].’” verlinkt, aus:

Den Satz verstehe ich nicht ganz?

Wenn ich die PHP-Datei im Browser aufrufe, sind innerhalb der Beschreibungen die HTML-Tags codiert - meinst du das damit?

Monatsmarktin der Innenstadt

Völklingen. Heute kann man in Völklingen „Marktflair erleben“, so lautet auch das Motto des von acht bis 18 Uhr in Völklingen stattfindenden Monatsmarktes. Er findet in der Forbacher Passage, der City-Promenade, dem Pfarrgarten und auf dem Adolph-Kolping-Platz statt. Angeboten werden &#8230; <a href="http://www.voelklingen-im-wandel.de/nachrichten/monatsmarktin-der-innenstadt/">Weiterlesen <span class="meta-nav">&#8594;</span></a>

Dazu würde ich den Parameter $encode von "auto" auf "no" ändern

getRssfeed("http://www.voelklingen-im-wandel.de/nachrichten/feed/","test","no",3,3);

24.05.2013 09:41 | geändert: 24.05.2013 09:44

3 Horst_M

Ich finde ja solche RegEx-Parser auch irgendwie schön und habe schon ein paar kleinere gebastelt. Doch gibt es bei normalen Feeds irgendwie Gründe, warum man die Feeds nicht einfach mit SimpleXML auslesen sollte?

Als ein Grund würde ich jetzt ansehen, dass auf CDATA Abschnitte kaum eine durch htmlspecialchars oder durch htmlentities abgesicherte Ausgabe möglich ist, ohne vorher HTML komplett auszufiltern. Nun sehe ich in dem Code aber, dass der Programmierer wohl die gleichen Probleme hatte und halte in dem Zusammenhang, falls ich das richtig erkenne, "no" für ein Sicherheitsleck.

Lieber würde ich CDATA von HTML entkernen. Ist noch nicht ganz fertig, verstehe auch gerade nicht, warum der den schließenden span-Tag nicht mit hinauswirft, doch so in etwa könnte das etwas werden, zumindest nach meiner bescheidenen Meinung:

<?php
$seite = "http://www.voelklingen-im-wandel.de/nachrichten/feed/";
$data  = file_get_contents($seite);

if($data != false) {

    $data = str_replace("content:encoded", "content", $data);
    $data = preg_replace("/<p>(.+?)<\/p>/s", "$1", $data);
    $data = preg_replace("/<span(.*?)>(.+?)<\/span>/s", "$2", $data);
    $data = preg_replace("/<br \/>/", "\n", $data);
    $data = preg_replace("/&(.+?);/", "", $data);

    $pxml = simplexml_load_string($data, "SimpleXMLElement", LIBXML_NOCDATA);

    $si =  0;
    $cw = 10;

    if($pxml->channel->item) {

        foreach ($pxml->channel->item as $nachricht) {

            if ($nachricht->title) {
                echo "<a href=\"".htmlspecialchars($nachricht->link)."\" target=\"_blank\">".htmlspecialchars($nachricht->title)."</a>";
            }
            if ($nachricht->content) {
                echo "<br>\n".htmlspecialchars($nachricht->description)."<br>\n";
            }
            if ($nachricht->content) {
                echo "<br>\n".htmlspecialchars($nachricht->content)."<br>\n";
            }
            if ($nachricht->link) {
                echo "<a href=\"".htmlspecialchars($nachricht->link)."\" target=\"_blank\">Linktext</a><br>\n";
            }
            if ($nachricht->pubDate) {
                echo "<br>".htmlspecialchars($nachricht->pubDate)."<br>\n<br>\n";
            }
            $si++;
            if ($si == $cw) {break;
            }
        }
    }
}
?>

25.05.2013 23:51

4 Horst_M

Habe mal noch etwas gebastelt, bis auf die enthaltenen Image-Tags sieht das Ding jetzt bereits mehr nach einem Feed aus. Biete einen für RSS und Atom zum Download an, doch der berücksichtigte da auch nicht alles, weil das eigentlich auch nur ein Übungsobjekt war.

Wenn ich mir das nun so ansehe, vielleicht wäre es gut (in etwa so wie begonnen), alle häufig in CDATA vorkommenden HTML-Tags erst einmal gegen BBCode auszutauschen, um dann bei der Ausgabe die erlaubten Tags wieder in HTML-Tags zu verwandeln. Dann sollte auch die Gefahr minimiert werden, dass jemand in einem Feed einen pixelgroßen iFrame einschleust, der eine andere Seite oder ein Script mit Schadcode nachladet. Oder was es da noch für Varianten geben mag, mit denen man rechnen müsste.

<?php
$seite = "http://www.voelklingen-im-wandel.de/nachrichten/feed/";
$data  = file_get_contents($seite);

if($data != false) {

    function wandleTags($daten) {

        $daten = str_replace("content:encoded", "content", $daten);
        $daten = str_replace("dc:creator", "creator", $daten);

        return $daten;
    }
    function filtereHTML($daten) {

        $daten = preg_replace("/<p.*?>(.+?)<\/p>/is", "$1[br]\n", $daten);
        $daten = preg_replace("/<div.*?>(.+?)<\/div>/is", "$1[br]\n", $daten);
        $daten = preg_replace("/<span.*?>(.*?)<\/span>/is", "$1", $daten);
        $daten = preg_replace("/<br \/>/i", "++\n", $daten);
        $daten = preg_replace("/&.+?;/", "", $daten);
        $daten = preg_replace("/<a href.+?>(.*?)<\/a>/is", "$1", $daten);
        $daten = str_replace("<b>", "[++b]", $daten);
        $daten = str_replace("</b>", "[++/b]", $daten);

        return $daten;
    }
    function formeHTML($daten) {

        $daten = str_replace("[br]", "<br \/>", $daten);
        $daten = str_replace("[++b]", "<b>", $daten);
        $daten = str_replace("[++/b]", "</b>", $daten);

        return $daten;
    }

    $pxml = simplexml_load_string(wandleTags($data), "SimpleXMLElement", LIBXML_NOCDATA);

    $si =  0;
    $cw = 10;

    if($pxml->channel->item) {

        foreach ($pxml->channel->item as $nachricht) {

            if ($nachricht->title) {
                echo "<a href=\"".htmlspecialchars($nachricht->link, ENT_QUOTES)."\" target=\"_blank\">".htmlspecialchars($nachricht->title, ENT_QUOTES)."</a>";
            }
            if ($nachricht->description) {
                echo "<br />\n".htmlspecialchars(filtereHTML($nachricht->description), ENT_QUOTES)."<br />\n";
            }
            if ($nachricht->content) {
               echo "<br />\n".formeHTML(htmlspecialchars(filtereHTML($nachricht->content), ENT_QUOTES))."<br />\n";
            }
            if ($nachricht->link) {
                echo "<a href=\"".htmlspecialchars($nachricht->link, ENT_QUOTES)."\" target=\"_blank\">Linktext</a><br />\n";
            }
            if ($nachricht->pubDate) {
                echo "<br />".htmlspecialchars(substr($nachricht->pubDate,  0, 16), ENT_QUOTES).
                     " um ".htmlspecialchars(substr($nachricht->pubDate, 17,  5), ENT_QUOTES)." Uhr";
            }
            if ($nachricht->creator) {
                echo " von ".htmlspecialchars($nachricht->creator, ENT_QUOTES)."<br />\n<br />\n";
            }
            echo "<hr />";
            $si++;
            if ($si == $cw) {break;
            }
        }
    }
}
?>

Edit: Ich sehe gerade, im Code werden hier einige BBC-Tags verschluckt. Die kennzeichne ich jetzt nachträglich mit ++ und das ++ sollte aus dem Script dann bei [++ wieder gelöscht werden.

Edit: Auf Images sollte dabei nicht verzichtet werden, nur eine Überprüfung auf Endung, Größe und MIME-Typ sollte stattfinden. Worauf man bei Feeds aus vertrauenswürdigen Quellen jedoch verzichten könnte.

26.05.2013 10:52 | geändert: 26.05.2013 11:30

5 AndreasH (Gast)

Hallo ihr beiden,

leider war ich beruflich die letzten Tage etwas im Treiben, so dass ich mich jetzt mal an den Test machen werde - ich werde euch gleich berichten!

VIELEN DANK aber schon jetzt für eure Mühe! -> Genial dieses Forum!

Gruß

26.05.2013 23:00

6 AndreasH (Gast)

Ich habe es nun nochmals versucht, .....

Das Ergebnis hier: http://www.voelklingen-im-wandel.de/indextest.php
-> Wie Sie sehen, sehen Sie leider noch immer nichts. :-(

Ich gebe es bald auf....

@Jörg:
Die "alte Codeversion" warf dem Seitenbesucher immer nur

" ’.['title'].’ ’.['title'].’ ’.['title'].’ ’.['title'].’ " aus.

Und die waren jeweils wie oben beschrieben verlinkt.

26.05.2013 23:14

7 Horst_M

Zitat von AndreasH
Das Ergebnis hier: http://www.voelklingen-im-wandel.de/indextest.php
-> Wie Sie sehen, sehen Sie leider noch immer nichts. :-(

Warum das bei Dir nicht funktioniert, das ist für mich nicht verständlich, zumal ich auf der angegebenen Seite "http://www.voelklingen-im-wandel.de/indextest.php" nur eine normale HTML-Seite sehe, doch nichts was mit einem RSS-Feed zu tun hat.

Bei meinem Listing habe ich noch die Zeile

$daten = preg_replace("/&.+?;/", "", $daten); 

von der Funktion filtereHTML() in die Funktion wandleTags() verschoben. Da überlege ich, ob es nicht besser wäre die jeweiligen Entities in ihre Hex-Entsprechungen wie \x0Ziffer zu verwandeln, zumindest die wichtigsten.

Weiterhin habe ich noch die Funktion filtereHTML um eine Zeile ergänzt

$daten = preg_replace("/<img.*?src=\"(.+?)\.(jpg|png).*?\/>/is", "[img]$1.$2[/img]", $daten);

und in der Funktion formeHTML() eine preg_replace_callback Funktion für Images eingefügt, damit auch Bilder geladen werden können, die mit Hilfe von getimagesize() überprüft werden.

Was mir noch nicht so richtig gefällt, ist halt die Anordnung von Bilduntertitel und Bildautor zu Images, einfach mit float dürfte das nicht zu lösen sein, weil beides dann zusammen erst einmal in einem gemeinsamen Bereich liegen müsste, um nur den restlichen Text umfließen zu lassen.

Habe verständlicherweise wenig Lust, mich in einen Feedreader nur für diesen Zweck zu verbeißen, somit werde ich da wohl vorläufig nicht weiter experimentieren. Nur so weit das Script fertig ist, soweit funktioniert es halt auch. Ein wenig müsstest Du schon noch selbst Hand anlegen.

27.05.2013 13:05

8 Horst_M

Habe mal das Script mit dem letzten Stand der Dinge online gestellt, weiß aber noch nicht, wie und wann es weiter gehen wird:

http://www.coder-welten.de/projekte/feedreader.htm

Einsatzfähig ist es zumindest und ein paar kleinere Anpassungen kann ja jeder selbst vornehmen.

27.05.2013 16:32

9 Horst_M

Weil ich es bisher vergessen hatte zu erwähnen, bei mir in der Testumgebung werden die Fehlermitteilungen auch ohne diese Zeilen ausgegeben, weil halt die Einstellungen so sind, doch falls das bei Dir nicht der Fall sein sollte, dann füge mal gleich zu Anfang im Script hinter dem öffnenden <?php Tag ein:

error_reporting(E_ALL);
ini_set("display_errors", true);

Und lasse Dir doch gleich hinter $data = file_get_contents($seite); anzeigen, ob der Feed vollständig geladen wird. Da muss ja etwas kommen und ausgegeben werden:

$data  = file_get_contents($seite);

echo "<pre>".htmlspecialchars($data, ENT_QUOTES)."</pre>";

27.05.2013 17:37 | geändert: 27.05.2013 17:38

10 AndreasH (Gast)

Hallo Horst,

danke für deine Unterstützung!!!
Also der Fehler deutet darauf hin, dass ich in der php.ini
allow_url_fopen auf "on" schalten lassen müsste - mein Provider rät mir allerdings aus Sicherheitsgründen dringend davon ab, ich sollte curl nutzen - was ich allerdings noch nie getan habe.

Kennt sich damit jemand aus? Ansonsten werde ich vorerste das Sicherheitsrisiko eingehen.

Hier noch die Fehlermeldung, aus der ich das schließe:
www.voelklingen-im-wandel.de/itest.php

29.05.2013 11:53