diff --git a/dist/nginx.conf b/dist/nginx.conf index 5e11859..c7dce50 100644 --- a/dist/nginx.conf +++ b/dist/nginx.conf @@ -7,7 +7,7 @@ server { #auth_basic "Advanced RSS Environment"; root /usr/share/arsse/www; index index.html; - + location / { try_files $uri $uri/ =404; } @@ -22,11 +22,11 @@ server { auth_basic off; include /usr/share/arsse/dist/nginx-fcgi.conf; } - + # NextCloud News protocol location /index.php/apps/news/api { try_files $uri @arsse_auth; - + location ~ ^/index\.php/apps/news/api/?$ { try_files $uri @arsse_no_auth; } @@ -48,4 +48,4 @@ server { root /usr/share/arsse/www; try_files $uri =404; } -} \ No newline at end of file +} diff --git a/lib/Arsse.php b/lib/Arsse.php index fc7ba4b..5300df6 100644 --- a/lib/Arsse.php +++ b/lib/Arsse.php @@ -8,7 +8,7 @@ namespace JKingWeb\Arsse; class Arsse { const VERSION = "0.4.0"; - + /** @var Lang */ public static $lang; /** @var Conf */ diff --git a/lib/CLI.php b/lib/CLI.php index 2cf84cd..1605efe 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -8,7 +8,7 @@ namespace JKingWeb\Arsse; class CLI { protected $args = []; - + protected function usage(): string { $prog = basename($_SERVER['argv'][0]); return <<db->prepare("SELECT value from arsse_meta where key = ?", "str")->run($key)->getValue(); } - + public function metaSet(string $key, $value, string $type = "str"): bool { $out = $this->db->prepare("UPDATE arsse_meta set value = ? where key = ?", $type, "str")->run($value, $key)->changes(); if (!$out) { @@ -444,7 +444,7 @@ class Database { target as (select ? as user, ? as source, ? as dest, ? as rename), folders as (SELECT id from arsse_folders join target on owner = user and coalesce(parent,0) = source union select arsse_folders.id as id from arsse_folders join folders on arsse_folders.parent=folders.id) ". - "SELECT + "SELECT ((select dest from target) is null or exists(select id from arsse_folders join target on owner = user and coalesce(id,0) = coalesce(dest,0))) as extant, not exists(select id from folders where id = coalesce((select dest from target),0)) as valid, not exists(select id from arsse_folders join target on coalesce(parent,0) = coalesce(dest,0) and name = coalesce((select rename from target),(select name from arsse_folders join target on id = source))) as available @@ -524,16 +524,16 @@ class Database { $folder = $this->folderValidateId($user, $folder)['id']; // create a complex query $q = new Query( - "SELECT + "SELECT arsse_subscriptions.id as id, feed,url,favicon,source,folder,pinned,err_count,err_msg,order_type,added, arsse_feeds.updated as updated, topmost.top as top_folder, coalesce(arsse_subscriptions.title, arsse_feeds.title) as title, (SELECT count(*) from arsse_articles where feed = arsse_subscriptions.feed) - (SELECT count(*) from arsse_marks where subscription = arsse_subscriptions.id and read = 1) as unread - from arsse_subscriptions - join user on user = owner - join arsse_feeds on feed = arsse_feeds.id + from arsse_subscriptions + join user on user = owner + join arsse_feeds on feed = arsse_feeds.id left join topmost on folder=f_id" ); $q->setOrder("pinned desc, title collate nocase"); @@ -673,7 +673,7 @@ class Database { $feeds = $this->db->query("SELECT id from arsse_feeds where next_fetch <= CURRENT_TIMESTAMP")->getAll(); return array_column($feeds, 'id'); } - + public function feedUpdate($feedID, bool $throwError = false): bool { // check to make sure the feed exists if (!ValueInfo::id($feedID)) { @@ -874,13 +874,13 @@ class Database { $extraColumns .= ","; } $q = new Query( - "SELECT + "SELECT $extraColumns arsse_articles.id as id, arsse_articles.feed as feed, arsse_articles.modified as modified_date, max( - arsse_articles.modified, + arsse_articles.modified, coalesce((select modified from arsse_marks where article = arsse_articles.id and subscription in (select sub from subscribed_feeds)),''), coalesce((select modified from arsse_label_members where article = arsse_articles.id and subscription in (select sub from subscribed_feeds)),'') ) as marked_date, @@ -1137,17 +1137,17 @@ class Database { ]; // the two queries we want to execute to make the requested changes $queries = [ - "UPDATE arsse_marks - set + "UPDATE arsse_marks + set read = case when (select honour_read from target_articles where target_articles.id = article) = 1 then (select read from target_values) else read end, starred = coalesce((select starred from target_values),starred), note = coalesce((select note from target_values),note), - modified = CURRENT_TIMESTAMP - WHERE + modified = CURRENT_TIMESTAMP + WHERE subscription in (select sub from subscribed_feeds) and article in (select id from target_articles where to_insert = 0 and (honour_read = 1 or honour_star = 1 or (select note from target_values) is not null))", "INSERT INTO arsse_marks(subscription,article,read,starred,note) - select + select (select id from arsse_subscriptions join user on user = owner where arsse_subscriptions.feed = target_articles.feed), id, coalesce((select read from target_values) * honour_read,0), @@ -1238,18 +1238,18 @@ class Database { public function articleCleanup(): bool { $query = $this->db->prepare( "WITH target_feed(id,subs) as (". - "SELECT + "SELECT id, (select count(*) from arsse_subscriptions where feed = arsse_feeds.id) as subs from arsse_feeds where id = ?". "), excepted_articles(id,edition) as (". - "SELECT - arsse_articles.id, (select max(id) from arsse_editions where article = arsse_articles.id) as edition + "SELECT + arsse_articles.id, (select max(id) from arsse_editions where article = arsse_articles.id) as edition from arsse_articles - join target_feed on arsse_articles.feed = target_feed.id + join target_feed on arsse_articles.feed = target_feed.id order by edition desc limit ?". ") ". - "DELETE from arsse_articles where - feed = (select max(id) from target_feed) + "DELETE from arsse_articles where + feed = (select max(id) from target_feed) and id not in (select id from excepted_articles) and (select count(*) from arsse_marks where article = arsse_articles.id and starred = 1) = 0 and ( @@ -1282,13 +1282,13 @@ class Database { throw new Db\ExceptionInput("typeViolation", ["action" => $this->caller(), "field" => "article", 'type' => "int > 0"]); // @codeCoverageIgnore } $out = $this->db->prepare( - "SELECT - arsse_articles.id as article, + "SELECT + arsse_articles.id as article, (select max(id) from arsse_editions where article = arsse_articles.id) as edition FROM arsse_articles join arsse_feeds on arsse_feeds.id = arsse_articles.feed join arsse_subscriptions on arsse_subscriptions.feed = arsse_feeds.id - WHERE + WHERE arsse_articles.id = ? and arsse_subscriptions.owner = ?", "int", "str" @@ -1304,15 +1304,15 @@ class Database { throw new Db\ExceptionInput("typeViolation", ["action" => $this->caller(), "field" => "edition", 'type' => "int > 0"]); // @codeCoverageIgnore } $out = $this->db->prepare( - "SELECT - arsse_editions.id as edition, + "SELECT + arsse_editions.id as edition, arsse_editions.article as article, (arsse_editions.id = (select max(id) from arsse_editions where article = arsse_editions.article)) as current FROM arsse_editions join arsse_articles on arsse_editions.article = arsse_articles.id join arsse_feeds on arsse_feeds.id = arsse_articles.feed join arsse_subscriptions on arsse_subscriptions.feed = arsse_feeds.id - WHERE + WHERE edition = ? and arsse_subscriptions.owner = ?", "int", "str" @@ -1359,10 +1359,10 @@ class Database { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } return $this->db->prepare( - "SELECT + "SELECT id,name, (select count(*) from arsse_label_members where label = id and assigned = 1) as articles, - (select count(*) from arsse_label_members + (select count(*) from arsse_label_members join arsse_marks on arsse_label_members.article = arsse_marks.article and arsse_label_members.subscription = arsse_marks.subscription where label = id and assigned = 1 and read = 1 ) as read @@ -1395,10 +1395,10 @@ class Database { $field = $byName ? "name" : "id"; $type = $byName ? "str" : "int"; $out = $this->db->prepare( - "SELECT + "SELECT id,name, (select count(*) from arsse_label_members where label = id and assigned = 1) as articles, - (select count(*) from arsse_label_members + (select count(*) from arsse_label_members join arsse_marks on arsse_label_members.article = arsse_marks.article and arsse_label_members.subscription = arsse_marks.subscription where label = id and assigned = 1 and read = 1 ) as read @@ -1484,11 +1484,11 @@ class Database { $q->setWhere("not exists(select article from arsse_label_members where label = ? and article = arsse_articles.id)", "int", $id); $q->pushCTE("target_articles"); $q->setBody( - "INSERT INTO - arsse_label_members(label,article,subscription) - SELECT + "INSERT INTO + arsse_label_members(label,article,subscription) + SELECT ?,id, - (select id from arsse_subscriptions join user on user = owner where arsse_subscriptions.feed = target_articles.feed) + (select id from arsse_subscriptions join user on user = owner where arsse_subscriptions.feed = target_articles.feed) FROM target_articles", "int", $id diff --git a/lib/Db/AbstractDriver.php b/lib/Db/AbstractDriver.php index 2cd8969..9d2867b 100644 --- a/lib/Db/AbstractDriver.php +++ b/lib/Db/AbstractDriver.php @@ -76,7 +76,7 @@ abstract class AbstractDriver implements Driver { public function begin(bool $lock = false): Transaction { return new Transaction($this, $lock); } - + public function savepointCreate(bool $lock = false): int { if ($lock && !$this->transDepth) { $this->lock(); diff --git a/lib/Db/Driver.php b/lib/Db/Driver.php index bf3bb28..56f5e8d 100644 --- a/lib/Db/Driver.php +++ b/lib/Db/Driver.php @@ -12,7 +12,7 @@ interface Driver { const TR_ROLLBACK = 2; const TR_PEND_COMMIT = -1; const TR_PEND_ROLLBACK = -2; - + public static function create(): Driver; // returns a human-friendly name for the driver (for display in installer, for example) public static function driverName(): string; diff --git a/lib/Feed.php b/lib/Feed.php index 54b32a2..836ecc8 100644 --- a/lib/Feed.php +++ b/lib/Feed.php @@ -44,7 +44,7 @@ class Feed { libxml_use_internal_errors(false); return $out; } - + public function __construct(int $feedID = null, string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = '', bool $scrape = false) { // fetch the feed $this->resource = self::download($url, $lastModified, $etag, $username, $password); diff --git a/lib/Misc/Context.php b/lib/Misc/Context.php index 4ae64e1..5fd61ff 100644 --- a/lib/Misc/Context.php +++ b/lib/Misc/Context.php @@ -58,79 +58,79 @@ class Context { } return array_values(array_filter($spec)); } - + public function reverse(bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function limit(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function offset(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function folder(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function folderShallow(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function subscription(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function latestArticle(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function oldestArticle(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function latestEdition(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function oldestEdition(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function unread(bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function starred(bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function modifiedSince($spec = null) { $spec = Date::normalize($spec); return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function notModifiedSince($spec = null) { $spec = Date::normalize($spec); return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function markedSince($spec = null) { $spec = Date::normalize($spec); return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function notMarkedSince($spec = null) { $spec = Date::normalize($spec); return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function edition(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - + public function article(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } diff --git a/lib/REST/AbstractHandler.php b/lib/REST/AbstractHandler.php index 756ebe7..b1c74bb 100644 --- a/lib/REST/AbstractHandler.php +++ b/lib/REST/AbstractHandler.php @@ -24,7 +24,7 @@ abstract class AbstractHandler implements Handler { } return $out; } - + protected function fieldMapTypes(array $data, array $map, string $dateFormat = "sql"): array { foreach ($map as $key => $type) { if (array_key_exists($key, $data)) { diff --git a/lib/REST/NextCloudNews/V1_2.php b/lib/REST/NextCloudNews/V1_2.php index 51e1606..eb78d96 100644 --- a/lib/REST/NextCloudNews/V1_2.php +++ b/lib/REST/NextCloudNews/V1_2.php @@ -74,7 +74,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { '/status' => ['GET' => "serverStatus"], '/user' => ['GET' => "userStatus"], ]; - + public function __construct() { } @@ -152,7 +152,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { $target->query = ""; return (string) $target; } - + protected function chooseCall(string $url, string $method): string { // // normalize the URL path: change any IDs to 1 for easier comparison $url = $this->normalizePathIds($url); @@ -282,7 +282,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { return new EmptyResponse(404); } } - + // list folders protected function folderList(array $url, array $data): ResponseInterface { $folders = []; @@ -362,7 +362,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { } return new EmptyResponse(204); } - + // return list of feeds which should be refreshed protected function feedListStale(array $url, array $data): ResponseInterface { // function requires admin rights per spec @@ -378,7 +378,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { } return new Response(['feeds' => $out]); } - + // refresh a feed protected function feedUpdate(array $url, array $data): ResponseInterface { // function requires admin rights per spec @@ -431,7 +431,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { } return new Response($out); } - + // return list of feeds for the logged-in user protected function subscriptionList(array $url, array $data): ResponseInterface { $subs = Arsse::$db->subscriptionList(Arsse::$user->id); diff --git a/lib/REST/Target.php b/lib/REST/Target.php index e04a0e2..c3e28fe 100644 --- a/lib/REST/Target.php +++ b/lib/REST/Target.php @@ -14,7 +14,7 @@ class Target { public $path = []; public $query = ""; public $fragment = ""; - + public function __construct(string $target) { $target = $this->parseFragment($target); $target = $this->parseQuery($target); diff --git a/lib/REST/TinyTinyRSS/API.php b/lib/REST/TinyTinyRSS/API.php index eb0aaad..57bb5a8 100644 --- a/lib/REST/TinyTinyRSS/API.php +++ b/lib/REST/TinyTinyRSS/API.php @@ -87,7 +87,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { 'status' => 1, 'content' => ['error' => "MALFORMED_INPUT"], ]; - + public function __construct() { } @@ -174,7 +174,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { public function opGetApiLevel(array $data): array { return ['level' => self::LEVEL]; } - + public function opGetVersion(array $data): array { return [ 'version' => self::VERSION, @@ -186,7 +186,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { $user = $data['user'] ?? ""; $pass = $data['password'] ?? ""; if (!Arsse::$conf->userSessionEnforced && isset(Arsse::$user->id)) { - // if HTTP authentication was previously successful and sessions + // if HTTP authentication was previously successful and sessions // are not enforced, create a session for the HTTP user regardless // of which user the API call mentions $id = Arsse::$db->sessionCreate(Arsse::$user->id); diff --git a/lib/REST/TinyTinyRSS/Exception.php b/lib/REST/TinyTinyRSS/Exception.php index b158def..da5a3c8 100644 --- a/lib/REST/TinyTinyRSS/Exception.php +++ b/lib/REST/TinyTinyRSS/Exception.php @@ -8,7 +8,7 @@ namespace JKingWeb\Arsse\REST\TinyTinyRSS; class Exception extends \Exception { protected $data = []; - + public function __construct($msg = "UNSPECIFIED_ERROR", $data = [], $e = null) { $this->data = $data; parent::__construct($msg, 0, $e); diff --git a/lib/Service.php b/lib/Service.php index 9dfed5b..5a51fc1 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -9,7 +9,7 @@ namespace JKingWeb\Arsse; use JKingWeb\Arsse\Misc\Date; class Service { - + /** @var Service\Driver */ protected $drv; /** @var \DateInterval */ @@ -26,7 +26,7 @@ class Service { } return $classes; } - + public static function interval(): \DateInterval { try { return new \DateInterval(Arsse::$conf->serviceFrequency); diff --git a/lib/Service/Curl/Driver.php b/lib/Service/Curl/Driver.php index 4d7435b..cfb73d4 100644 --- a/lib/Service/Curl/Driver.php +++ b/lib/Service/Curl/Driver.php @@ -12,7 +12,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { protected $options = []; protected $queue; protected $handles = []; - + public static function driverName(): string { return Arsse::$lang->msg("Driver.Service.Curl.Name"); } diff --git a/lib/Service/Forking/Driver.php b/lib/Service/Forking/Driver.php index d1e68fd..4a8e7bf 100644 --- a/lib/Service/Forking/Driver.php +++ b/lib/Service/Forking/Driver.php @@ -10,7 +10,7 @@ use JKingWeb\Arsse\Arsse; class Driver implements \JKingWeb\Arsse\Service\Driver { protected $queue = []; - + public static function driverName(): string { return Arsse::$lang->msg("Driver.Service.Forking.Name"); } @@ -18,7 +18,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { public static function requirementsMet(): bool { return function_exists("popen"); } - + public function __construct() { } diff --git a/lib/Service/Internal/Driver.php b/lib/Service/Internal/Driver.php index ba23391..06e91ce 100644 --- a/lib/Service/Internal/Driver.php +++ b/lib/Service/Internal/Driver.php @@ -10,7 +10,7 @@ use JKingWeb\Arsse\Arsse; class Driver implements \JKingWeb\Arsse\Service\Driver { protected $queue = []; - + public static function driverName(): string { return Arsse::$lang->msg("Driver.Service.Internal.Name"); } @@ -19,7 +19,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { // this driver has no requirements return true; } - + public function __construct() { } diff --git a/locale/en.php b/locale/en.php index a6d1698..477f04a 100644 --- a/locale/en.php +++ b/locale/en.php @@ -5,7 +5,7 @@ return [ 'API.TTRSS.Category.Uncategorized' => 'Uncategorized', - 'API.TTRSS.Category.Special' => 'Special', + 'API.TTRSS.Category.Special' => 'Special', 'API.TTRSS.Category.Labels' => 'Labels', 'API.TTRSS.Feed.All' => 'All articles', 'API.TTRSS.Feed.Fresh' => 'Fresh articles', @@ -181,4 +181,4 @@ return [ 'Exception.JKingWeb/Arsse/Feed/Exception.xmlEntity' => 'Refused to parse feed "{url}" because it contains an XXE attack', 'Exception.JKingWeb/Arsse/Feed/Exception.subscriptionNotFound' => 'Unable to find a feed at location "{url}"', 'Exception.JKingWeb/Arsse/Feed/Exception.unsupportedFeedFormat' => 'Feed "{url}" is of an unsupported format', -]; \ No newline at end of file +]; diff --git a/sql/SQLite3/0.sql b/sql/SQLite3/0.sql index e4cc5e4..add9b56 100644 --- a/sql/SQLite3/0.sql +++ b/sql/SQLite3/0.sql @@ -105,7 +105,7 @@ create table arsse_marks( subscription integer not null references arsse_subscriptions(id) on delete cascade on update cascade, read boolean not null default 0, starred boolean not null default 0, - modified text not null default CURRENT_TIMESTAMP, + modified text not null default CURRENT_TIMESTAMP, primary key(article,subscription) ); @@ -124,4 +124,4 @@ create table arsse_categories( -- set version marker pragma user_version = 1; -insert into arsse_meta(key,value) values('schema_version','1'); \ No newline at end of file +insert into arsse_meta(key,value) values('schema_version','1'); diff --git a/tests/cases/Db/SQLite3/TestStatement.php b/tests/cases/Db/SQLite3/TestStatement.php index 5a195a8..4530ea3 100644 --- a/tests/cases/Db/SQLite3/TestStatement.php +++ b/tests/cases/Db/SQLite3/TestStatement.php @@ -49,7 +49,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $typeStr = "'".str_replace("'", "''", $type)."'"; $nativeStatement = $this->c->prepare( "SELECT ( - (CASE WHEN substr($typeStr, 0, 7) <> 'strict ' then null else 1 end) is null + (CASE WHEN substr($typeStr, 0, 7) <> 'strict ' then null else 1 end) is null and ? is null ) or ( $exp = ? @@ -250,7 +250,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { [$dateImmutable, "strict boolean", "1"], ]; } - + public function testConstructStatement() { $nativeStatement = $this->c->prepare("SELECT ? as value"); $this->assertInstanceOf(Statement::class, new \JKingWeb\Arsse\Db\SQLite3\Statement($this->c, $nativeStatement)); diff --git a/tests/cases/Db/SQLite3PDO/TestStatement.php b/tests/cases/Db/SQLite3PDO/TestStatement.php index 8fe7086..6ea2a4a 100644 --- a/tests/cases/Db/SQLite3PDO/TestStatement.php +++ b/tests/cases/Db/SQLite3PDO/TestStatement.php @@ -50,7 +50,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $typeStr = "'".str_replace("'", "''", $type)."'"; $nativeStatement = $this->c->prepare( "SELECT ( - (CASE WHEN substr($typeStr, 0, 7) <> 'strict ' then null else 1 end) is null + (CASE WHEN substr($typeStr, 0, 7) <> 'strict ' then null else 1 end) is null and ? is null ) or ( $exp = ? diff --git a/tests/cases/Feed/TestFeed.php b/tests/cases/Feed/TestFeed.php index d458c4a..fde0195 100644 --- a/tests/cases/Feed/TestFeed.php +++ b/tests/cases/Feed/TestFeed.php @@ -172,7 +172,7 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertException("malformedXml", "Feed"); new Feed(null, $this->base."Parsing/Malformed"); } - + public function testDeduplicateFeedItems() { // duplicates with dates lead to the newest match being kept $t = strtotime("2002-05-19T15:21:36Z"); @@ -245,7 +245,7 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { $f = new Feed(null, $this->base."Caching/200None"); $this->assertTime($t, $f->lastModified); } - + public function testComputeNextFetchOnError() { for ($a = 0; $a < 100; $a++) { if ($a < 3) { @@ -257,7 +257,7 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { } } } - + public function testComputeNextFetchFrom304() { // if less than half an hour, check in 15 minutes $t = strtotime("now"); @@ -305,7 +305,7 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { $exp = strtotime("now + 3 hours"); $this->assertTime($exp, $f->nextFetch); } - + public function testComputeNextFetchFrom200() { // if less than half an hour, check in 15 minutes $f = new Feed(null, $this->base."NextFetch/30m"); diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index 8c2f12d..e6dbdf4 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -16,7 +16,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp() { $this->clearData(); } - + public function testGetIntegerInfo() { $tests = [ [null, I::NULL], diff --git a/tests/cases/REST/NextCloudNews/TestV1_2.php b/tests/cases/REST/NextCloudNews/TestV1_2.php index ab4baad..2ee0b1b 100644 --- a/tests/cases/REST/NextCloudNews/TestV1_2.php +++ b/tests/cases/REST/NextCloudNews/TestV1_2.php @@ -934,7 +934,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { $exp = new EmptyResponse(403); $this->assertMessage($exp, $this->req("GET", "/cleanup/before-update")); } - + public function testCleanUpAfterUpdate() { Phake::when(Arsse::$db)->articleCleanup()->thenReturn(true); $exp = new EmptyResponse(204); diff --git a/tests/cases/REST/TestREST.php b/tests/cases/REST/TestREST.php index dac6b25..ebfd79d 100644 --- a/tests/cases/REST/TestREST.php +++ b/tests/cases/REST/TestREST.php @@ -60,7 +60,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { [$fake, "/full/url-not", []], ]; } - + /** @dataProvider provideAuthenticableRequests */ public function testAuthenticateRequests(array $serverParams, array $expAttr) { $r = new REST(); @@ -105,7 +105,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { $act = $r->challenge($in); $this->assertMessage($exp, $act); } - + /** @dataProvider provideUnnormalizedOrigins */ public function testNormalizeOrigins(string $origin, string $exp, array $ports = null) { $r = new REST(); diff --git a/tests/cases/REST/TinyTinyRSS/TestAPI.php b/tests/cases/REST/TinyTinyRSS/TestAPI.php index 278d1cf..2fc7104 100644 --- a/tests/cases/REST/TinyTinyRSS/TestAPI.php +++ b/tests/cases/REST/TinyTinyRSS/TestAPI.php @@ -105,21 +105,21 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { protected $richContent = <<

- Pour vous faire mieux - connaitre d’ou\u{300} vient - l’erreur de ceux qui - bla\u{302}ment la - volupte\u{301}, et qui louent - en quelque sorte la douleur, - je vais entrer dans une - explication plus - e\u{301}tendue, et vous faire - voir tout ce qui a - e\u{301}te\u{301} dit - la\u{300}-dessus par - l’inventeur de la - ve\u{301}rite\u{301}, et, pour - ainsi dire, par l’architecte + Pour vous faire mieux + connaitre d’ou\u{300} vient + l’erreur de ceux qui + bla\u{302}ment la + volupte\u{301}, et qui louent + en quelque sorte la douleur, + je vais entrer dans une + explication plus + e\u{301}tendue, et vous faire + voir tout ce qui a + e\u{301}te\u{301} dit + la\u{300}-dessus par + l’inventeur de la + ve\u{301}rite\u{301}, et, pour + ainsi dire, par l’architecte de la vie heureuse.

@@ -157,7 +157,7 @@ LONG_STRING; protected function reqAuth($data, $user) { return $this->req($data, "POST", "", null, $user); } - + protected function respGood($content = null, $seq = 0): Response { return new Response([ 'seq' => $seq, @@ -1551,7 +1551,7 @@ LONG_STRING; ['op' => "updateArticle", 'sid' => "PriestsOfSyrinx", 'article_ids' => "42, 2112, -1", 'field' => 0, 'mode' => 1], ['op' => "updateArticle", 'sid' => "PriestsOfSyrinx", 'article_ids' => "42, 2112, -1", 'field' => 0, 'mode' => 2], ['op' => "updateArticle", 'sid' => "PriestsOfSyrinx", 'article_ids' => "42, 2112, -1", 'field' => 0, 'mode' => 3], // invalid mode - + ['op' => "updateArticle", 'sid' => "PriestsOfSyrinx", 'article_ids' => "42, 2112, -1", 'field' => 1], // Published feed' no-op ['op' => "updateArticle", 'sid' => "PriestsOfSyrinx", 'article_ids' => "42, 2112, -1", 'field' => 1, 'mode' => 0], ['op' => "updateArticle", 'sid' => "PriestsOfSyrinx", 'article_ids' => "42, 2112, -1", 'field' => 1, 'mode' => 1], diff --git a/tests/cases/User/TestAuthorization.php b/tests/cases/User/TestAuthorization.php index 088f674..6bbb0fb 100644 --- a/tests/cases/User/TestAuthorization.php +++ b/tests/cases/User/TestAuthorization.php @@ -83,7 +83,7 @@ class TestAuthorization extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertFalse(Arsse::$user->authorizationEnabled(true)); $this->assertTrue(Arsse::$user->authorizationEnabled(true)); } - + public function testSelfActionLogic() { foreach (array_keys(self::USERS) as $user) { Arsse::$user->auth($user, ""); diff --git a/tests/docroot/Feed/Fetching/Timeout.php b/tests/docroot/Feed/Fetching/Timeout.php index cfa7c5f..ec7bee8 100644 --- a/tests/docroot/Feed/Fetching/Timeout.php +++ b/tests/docroot/Feed/Fetching/Timeout.php @@ -1,4 +1,4 @@ - 404, diff --git a/tests/docroot/Feed/Fetching/TooLarge.php b/tests/docroot/Feed/Fetching/TooLarge.php index ce20059..0fef567 100644 --- a/tests/docroot/Feed/Fetching/TooLarge.php +++ b/tests/docroot/Feed/Fetching/TooLarge.php @@ -1,4 +1,4 @@ - '.str_repeat("0", 1024).' diff --git a/tests/docroot/Feed/NextFetch/NotModified.php b/tests/docroot/Feed/NextFetch/NotModified.php index 6ed847a..d73769a 100644 --- a/tests/docroot/Feed/NextFetch/NotModified.php +++ b/tests/docroot/Feed/NextFetch/NotModified.php @@ -1,4 +1,4 @@ - 304, diff --git a/tests/docroot/Feed/Parsing/XXEAttack.php b/tests/docroot/Feed/Parsing/XXEAttack.php index dbe3866..8a38e14 100644 --- a/tests/docroot/Feed/Parsing/XXEAttack.php +++ b/tests/docroot/Feed/Parsing/XXEAttack.php @@ -1,8 +1,8 @@ "application/rss+xml", 'content' => << + ]> diff --git a/tests/lib/Database/SeriesCleanup.php b/tests/lib/Database/SeriesCleanup.php index 8e7eb83..532c18d 100644 --- a/tests/lib/Database/SeriesCleanup.php +++ b/tests/lib/Database/SeriesCleanup.php @@ -157,7 +157,7 @@ trait SeriesCleanup { } $this->compareExpectations($state); } - + public function testCleanUpOldArticlesWithUnlimitedReadRetention() { Arsse::$conf->purgeArticlesRead = ""; Arsse::$db->articleCleanup(); @@ -169,7 +169,7 @@ trait SeriesCleanup { } $this->compareExpectations($state); } - + public function testCleanUpOldArticlesWithUnlimitedUnreadRetention() { Arsse::$conf->purgeArticlesUnread = ""; Arsse::$db->articleCleanup(); diff --git a/tests/lib/Database/SeriesFeed.php b/tests/lib/Database/SeriesFeed.php index fcfaf6b..24a0097 100644 --- a/tests/lib/Database/SeriesFeed.php +++ b/tests/lib/Database/SeriesFeed.php @@ -30,7 +30,7 @@ trait SeriesFeed { 'title_content_hash' => '43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', ], ]; - + public function setUpSeries() { // set up the test data $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); diff --git a/tests/lib/Database/SeriesUser.php b/tests/lib/Database/SeriesUser.php index 6478017..9d65153 100644 --- a/tests/lib/Database/SeriesUser.php +++ b/tests/lib/Database/SeriesUser.php @@ -58,7 +58,7 @@ trait SeriesUser { $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userPasswordGet("admin@example.net"); } - + public function testAddANewUser() { $this->assertSame("", Arsse::$db->userAdd("john.doe@example.org", "")); Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userAdd"); @@ -99,7 +99,7 @@ trait SeriesUser { $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userAdd("john.doe@example.org", ""); } - + public function testRemoveAUser() { $this->assertTrue(Arsse::$db->userRemove("admin@example.net")); Phake::verify(Arsse::$user)->authorize("admin@example.net", "userRemove"); @@ -112,7 +112,7 @@ trait SeriesUser { $this->assertException("doesNotExist", "User"); Arsse::$db->userRemove("john.doe@example.org"); } - + public function testRemoveAUserWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); @@ -130,13 +130,13 @@ trait SeriesUser { $this->assertSame($users, Arsse::$db->userList("example.com")); Phake::verify(Arsse::$user)->authorize("@example.com", "userList"); } - + public function testListAllUsersWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userList(); } - + public function testListUsersOnADomainWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); @@ -166,7 +166,7 @@ trait SeriesUser { $this->assertException("doesNotExist", "User"); Arsse::$db->userPasswordSet("john.doe@example.org", "secret"); } - + public function testSetAPasswordWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); @@ -188,7 +188,7 @@ trait SeriesUser { $this->assertException("doesNotExist", "User"); Arsse::$db->userPropertiesGet("john.doe@example.org"); } - + public function testGetUserPropertiesWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); @@ -223,7 +223,7 @@ trait SeriesUser { $this->assertException("doesNotExist", "User"); Arsse::$db->userPropertiesSet("john.doe@example.org", $try); } - + public function testSetUserPropertiesWithoutAuthority() { $try = ['name' => 'John Doe']; Phake::when(Arsse::$user)->authorize->thenReturn(false); @@ -244,7 +244,7 @@ trait SeriesUser { $this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet("john.doe@example.org")); Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userRightsGet"); } - + public function testGetUserRightsWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); @@ -266,7 +266,7 @@ trait SeriesUser { $this->assertException("doesNotExist", "User"); Arsse::$db->userRightsSet("john.doe@example.org", $rights); } - + public function testSetUserRightsWithoutAuthority() { $rights = UserDriver::RIGHTS_GLOBAL_ADMIN; Phake::when(Arsse::$user)->authorize->thenReturn(false); diff --git a/www/tt-rss/images/README b/www/tt-rss/images/README index 86d8d68..38b7242 100644 --- a/www/tt-rss/images/README +++ b/www/tt-rss/images/README @@ -1,14 +1,14 @@ -Silk icon set v1.3 +Silk icon set v1.3 Copyright 2006, Mark James http://www.famfamfam.com/lab/icons/silk/ Used under license: http://creativecommons.org/licenses/by/2.5/ -A minimal subset of the Silk icon set used by Tiny Tiny RSS is included here -to provide consistent results with certain API functions. +A minimal subset of the Silk icon set used by Tiny Tiny RSS is included here +to provide consistent results with certain API functions. -Note that TT-RSS renames some of the icons, and we use the modified names, +Note that TT-RSS renames some of the icons, and we use the modified names, again for consistency. Below is a table listing the source file names: Modified Original