X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=classes%2Ffeedparser.php;h=a5e406149d46062c620b60a6ce53738f0b0d13d8;hb=HEAD;hp=4eaeb242900d0b244d43ba882f698341c8c06774;hpb=54f23d38a6d9e994575d2159b2277674149ae5d8;p=tt-rss.git diff --git a/classes/feedparser.php b/classes/feedparser.php index 4eaeb242..a5e40614 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -13,6 +13,20 @@ class FeedParser { const FEED_RSS = 1; const FEED_ATOM = 2; + function normalize_encoding($data) { + if (preg_match('/^(<\?xml[\t\n\r ].*?encoding[\t\n\r ]*=[\t\n\r ]*["\'])(.+?)(["\'].*?\?>)/s', $data, $matches) === 1) { + + $encoding = strtolower($matches[2]); + + if (in_array($encoding, array_map('strtolower', mb_list_encodings()))) + $data = mb_convert_encoding($data, 'UTF-8', $encoding); + + $data = preg_replace('/^<\?xml[\t\n\r ].*?\?>/s', $matches[1] . "UTF-8" . $matches[3] , $data); + } + + return $data; + } + function __construct($data) { libxml_use_internal_errors(true); libxml_clear_errors(); @@ -25,19 +39,15 @@ class FeedParser { // libxml compiled without iconv? if ($error && $error->code == 32) { - if (preg_match('/^(<\?xml[\t\n\r ].*?encoding[\t\n\r ]*=[\t\n\r ]*["\'])(.+?)(["\'].*?\?>)/s', $data, $matches) === 1) { - $data = mb_convert_encoding($data, 'UTF-8', $matches[2]); - - $data = preg_replace('/^<\?xml[\t\n\r ].*?\?>/s', $matches[1] . "UTF-8" . $matches[3] , $data); + $data = $this->normalize_encoding($data); - if ($data) { - libxml_clear_errors(); + if ($data) { + libxml_clear_errors(); - $this->doc = new DOMDocument(); - $this->doc->loadXML($data); + $this->doc = new DOMDocument(); + $this->doc->loadXML($data); - $error = libxml_get_last_error(); - } + $error = libxml_get_last_error(); } } @@ -45,6 +55,9 @@ class FeedParser { if ($error) { foreach (libxml_get_errors() as $err) { if ($err->code == 9) { + // if the source feed is not in utf8, next conversion will fail + $data = $this->normalize_encoding($data); + // remove dangling bytes $data = mb_convert_encoding($data, 'UTF-8', 'UTF-8'); @@ -88,12 +101,13 @@ class FeedParser { $xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); $xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/'); $xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/'); + $xpath->registerNamespace('thread', 'http://purl.org/syndication/thread/1.0'); $this->xpath = $xpath; $root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)"); - if ($root) { + if ($root && $root->length > 0) { $root = $root->item(0); if ($root) { @@ -105,6 +119,7 @@ class FeedParser { $this->type = $this::FEED_RSS; break; case "feed": + case "atom:feed": $this->type = $this::FEED_ATOM; break; default: @@ -130,9 +145,14 @@ class FeedParser { $link = $xpath->query("//atom:feed/atom:link[not(@rel)]")->item(0); + if (!$link) + $link = $xpath->query("//atom:feed/atom:link[@rel='alternate']")->item(0); + if (!$link) $link = $xpath->query("//atom03:feed/atom03:link[not(@rel)]")->item(0); + if (!$link) + $link = $xpath->query("//atom03:feed/atom03:link[@rel='alternate']")->item(0); if ($link && $link->hasAttributes()) { $this->link = $link->getAttribute("href"); @@ -195,6 +215,10 @@ class FeedParser { break; } + + if ($this->title) $this->title = trim($this->title); + if ($this->link) $this->link = trim($this->link); + } else { if( !isset($this->error) ){ $this->error = "Unknown/unsupported feed type"; @@ -242,7 +266,7 @@ class FeedParser { foreach ($links as $link) { if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) { - array_push($rv, $link->getAttribute('href')); + array_push($rv, trim($link->getAttribute('href'))); } } break; @@ -251,7 +275,7 @@ class FeedParser { foreach ($links as $link) { if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) { - array_push($rv, $link->getAttribute('href')); + array_push($rv, trim($link->getAttribute('href'))); } } break; @@ -259,4 +283,4 @@ class FeedParser { return $rv; } -} ?> +}