diff options
author | Sean Molenaar <SMillerDev@users.noreply.github.com> | 2019-03-17 08:23:37 +0100 |
---|---|---|
committer | Benjamin Brahmer <info@b-brahmer.de> | 2019-03-17 08:23:37 +0100 |
commit | 2698214c4122d4f5f63f26f7a204035fe0d4f211 (patch) | |
tree | e1a033654736cc68f698af7110e8e17fdb0c2e55 /lib | |
parent | f5e25d2edef3360ed7fcdc1ecc663cfb37b650b7 (diff) |
fix/allow CDATA encoding (#428)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AppInfo/Application.php | 8 | ||||
-rw-r--r-- | lib/Command/ShowFeed.php | 70 | ||||
-rw-r--r-- | lib/Config/FetcherConfig.php | 68 | ||||
-rw-r--r-- | lib/Db/Item.php | 4 | ||||
-rwxr-xr-x | lib/Fetcher/FeedFetcher.php | 13 | ||||
-rw-r--r-- | lib/Utility/ProxyConfigParser.php | 66 |
6 files changed, 120 insertions, 109 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 755f3ea70..06d6135dc 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -159,13 +159,9 @@ class Application extends App * Fetchers */ $container->registerService(FetcherConfig::class, function (IContainer $c): FetcherConfig { - // FIXME: move this into a separate class for testing? - $config = $c->query(Config::class); - $proxy = $c->query(ProxyConfigParser::class); - $fConfig = new FetcherConfig(); - $fConfig->setClientTimeout($config->getFeedFetcherTimeout()); - $fConfig->setProxy($proxy); + $fConfig->setConfig($c->query(Config::class)) + ->setProxy($c->query(IConfig::class)); return $fConfig; }); diff --git a/lib/Command/ShowFeed.php b/lib/Command/ShowFeed.php new file mode 100644 index 000000000..bbe1913fa --- /dev/null +++ b/lib/Command/ShowFeed.php @@ -0,0 +1,70 @@ +<?php +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Sean Molenaar <sean@seanmolenaar.eu> + * @copyright Sean Molenaar 2019 + */ +namespace OCA\News\Command; + +use FeedIo\FeedIo; +use Favicon\Favicon; + +use OCA\News\Fetcher\Fetcher; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * This is used for debugging feed data: + * ./occ news:show-feed www.feed.com + */ +class ShowFeed extends Command +{ + /** + * Feed and favicon fetcher. + */ + protected $feedFetcher; + + /** + * Set up class. + * + * @param Fetcher $feedFetcher Feed reader + */ + public function __construct(Fetcher $feedFetcher) + { + $this->feedFetcher = $feedFetcher; + parent::__construct(); + } + + protected function configure() + { + $this->setName('news:show-feed') + ->setDescription('Prints a JSON string which represents the given feed as it would be in the DB.') + ->addArgument('feed', InputArgument::REQUIRED, 'Feed to parse') + ->addOption('user', 'u', InputOption::VALUE_OPTIONAL, 'Username for the feed') + ->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Password for the feed'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $url = $input->getArgument('feed'); + $user = $input->getOption('user'); + $password = $input->getOption('password'); + + try { + list($feed, $items) = $this->feedFetcher->fetch($url, true, null, $user, $password); + $output->writeln("Feed: " . json_encode($feed, JSON_PRETTY_PRINT)); + $output->writeln("Items: " . json_encode($items, JSON_PRETTY_PRINT)); + } catch (\Throwable $ex) { + $output->writeln('<error>Failed to fetch feed info:</error>'); + $output->writeln($ex->getMessage()); + return 1; + } + } +} diff --git a/lib/Config/FetcherConfig.php b/lib/Config/FetcherConfig.php index 55603c47c..1459ff032 100644 --- a/lib/Config/FetcherConfig.php +++ b/lib/Config/FetcherConfig.php @@ -16,6 +16,7 @@ namespace OCA\News\Config; use FeedIo\Adapter\ClientInterface; use \GuzzleHttp\Client; use \FeedIo\Adapter\Guzzle\Client as FeedIoClient; +use OCP\IConfig; /** * Class FetcherConfig @@ -26,6 +27,8 @@ class FetcherConfig { protected $client_timeout; protected $proxy; + protected $redirects; + protected $max_size; /** * Configure a guzzle client @@ -36,14 +39,18 @@ class FetcherConfig { if (!class_exists('GuzzleHttp\Collection')) { $config = [ - 'timeout' => $this->getClientTimeout(), + 'timeout' => $this->client_timeout, ]; if (!empty($this->proxy)) { $config['proxy'] = $this->proxy; } - $guzzle = new Client(); + if (!empty($this->redirects)) { + $config['redirect.max'] = $this->redirects; + } + + $guzzle = new Client($config); $client = new FeedIoClient($guzzle); return $client; @@ -51,7 +58,7 @@ class FetcherConfig $config = [ 'request.options' => [ - 'timeout' => $this->getClientTimeout(), + 'timeout' => $this->client_timeout, ], ]; @@ -59,59 +66,54 @@ class FetcherConfig $config['request.options']['proxy'] = $this->proxy; } + if (!empty($this->redirects)) { + $config['request.options']['redirect.max'] = $this->redirects; + } + $guzzle = new Client($config); return new LegacyGuzzleClient($guzzle); } /** - * Set a timeout for the client + * Set settings for config. * - * @param int $timeout The timeout + * @param Config $config The shared configuration * * @return self */ - public function setClientTimeout($timeout) + public function setConfig(Config $config) { - $this->client_timeout = $timeout; + $this->client_timeout = $config->getFeedFetcherTimeout(); + $this->redirects = $config->getMaxRedirects(); + $this->max_size = $config->getMaxSize(); return $this; } /** - * Get the client timeout. - * - * @return mixed - */ - public function getClientTimeout() - { - return $this->client_timeout; - } - - /** * Set the proxy * - * @param \OCA\News\Utility\ProxyConfigParser $proxy The proxy to set. + * @param IConfig $config Nextcloud config. * * @return self */ - public function setProxy($proxy) + public function setProxy(IConfig $config) { - // proxy settings - $proxySettings = $proxy->parse(); - $host = $proxySettings['host']; - $port = $proxySettings['port']; - $user = $proxySettings['user']; - $password = $proxySettings['password']; - - $proxy_string = 'https://'; - if (!empty($user)) { - $proxy_string .= $user . ':' . $password . '@'; + $proxy = $config->getSystemValue('proxy', null); + $creds = $config->getSystemValue('proxyuserpwd', null); + + if (is_null($proxy)) { + return $this; } - $proxy_string .= $host; - if (!empty($port)) { - $proxy_string .= ':' . $port; + + $url = new \Net_URL2($proxy); + + if ($creds) { + $auth = explode(':', $creds, 2); + $url->setUserinfo($auth[0], $auth[1]); } - $this->proxy = $proxy_string; + + $this->proxy = $url->getNormalizedURL(); return $this; } diff --git a/lib/Db/Item.php b/lib/Db/Item.php index 3a17dd2cb..710f239d4 100644 --- a/lib/Db/Item.php +++ b/lib/Db/Item.php @@ -146,7 +146,7 @@ class Item extends Entity implements IAPI, \JsonSerializable return $this->enclosureMime; } - public function getFeedId(): int + public function getFeedId() { return $this->feedId; } @@ -169,7 +169,7 @@ class Item extends Entity implements IAPI, \JsonSerializable return $this->guidHash; } - public function getId(): int + public function getId() { return $this->id; } diff --git a/lib/Fetcher/FeedFetcher.php b/lib/Fetcher/FeedFetcher.php index 9b4a2f996..fb9da7919 100755 --- a/lib/Fetcher/FeedFetcher.php +++ b/lib/Fetcher/FeedFetcher.php @@ -19,12 +19,14 @@ use FeedIo\Feed\ItemInterface; use FeedIo\FeedInterface; use FeedIo\FeedIo; +use Net_URL2; use OCA\News\Utility\PsrLogger; use OCP\IL10N; use OCA\News\Db\Item; use OCA\News\Db\Feed; use OCA\News\Utility\Time; +use SimpleXMLElement; class FeedFetcher implements IFeedFetcher { @@ -65,10 +67,11 @@ class FeedFetcher implements IFeedFetcher */ public function fetch(string $url, bool $favicon, $lastModified, $user, $password): array { + $url2 = new Net_URL2($url); if (!empty($user) && !empty(trim($user))) { - $url = explode('://', $url); - $url = $url[0] . '://' . urlencode($user) . ':' . urlencode($password) . '@' . $url[1]; + $url2->setUserinfo(urlencode($user), urlencode($password)); } + $url = $url2->getNormalizedURL(); if (is_null($lastModified) || !is_string($lastModified)) { $resource = $this->reader->read($url); } else { @@ -204,6 +207,12 @@ class FeedFetcher implements IFeedFetcher 'HTML-ENTITIES', mb_detect_encoding($body) ); + $data = simplexml_load_string( + '<?xml version="1.0" encoding="utf-8"?><item>' . $body . '</item>', + SimpleXMLElement::class, + LIBXML_NOCDATA + ); + $body = ($data === false) ? $body : (string) $data; $item->setBody($body); if ($parsedItem->hasMedia()) { diff --git a/lib/Utility/ProxyConfigParser.php b/lib/Utility/ProxyConfigParser.php deleted file mode 100644 index dc9bd3d8b..000000000 --- a/lib/Utility/ProxyConfigParser.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php -/** - * Nextcloud - News - * - * This file is licensed under the Affero General Public License version 3 or - * later. See the COPYING file. - * - * @author Alessandro Cosentino <cosenal@gmail.com> - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @copyright 2012 Alessandro Cosentino - * @copyright 2012-2014 Bernhard Posselt - */ - - -namespace OCA\News\Utility; - -use \OCP\IConfig; - -class ProxyConfigParser -{ - - private $config; - - public function __construct(IConfig $config) - { - $this->config = $config; - } - - - /** - * Parses the config and splits up the port + url - * - * @return array - */ - public function parse() - { - $proxy = $this->config->getSystemValue('proxy'); - $userpasswd = $this->config->getSystemValue('proxyuserpwd'); - - $result = [ - 'host' => null, - 'port' => null, - 'user' => null, - 'password' => null - ]; - - // we need to filter out the port -.- - $url = new \Net_URL2($proxy); - $port = $url->getPort(); - - $url->setPort(false); - $host = $url->getUrl(); - - - $result['host'] = $host; - $result['port'] = $port; - - if ($userpasswd) { - $auth = explode(':', $userpasswd, 2); - $result['user'] = $auth[0]; - $result['password'] = $auth[1]; - } - - return $result; - } -} |