summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSean Molenaar <SMillerDev@users.noreply.github.com>2019-03-17 08:23:37 +0100
committerBenjamin Brahmer <info@b-brahmer.de>2019-03-17 08:23:37 +0100
commit2698214c4122d4f5f63f26f7a204035fe0d4f211 (patch)
treee1a033654736cc68f698af7110e8e17fdb0c2e55 /lib
parentf5e25d2edef3360ed7fcdc1ecc663cfb37b650b7 (diff)
fix/allow CDATA encoding (#428)
Diffstat (limited to 'lib')
-rw-r--r--lib/AppInfo/Application.php8
-rw-r--r--lib/Command/ShowFeed.php70
-rw-r--r--lib/Config/FetcherConfig.php68
-rw-r--r--lib/Db/Item.php4
-rwxr-xr-xlib/Fetcher/FeedFetcher.php13
-rw-r--r--lib/Utility/ProxyConfigParser.php66
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;
- }
-}