Bladeren bron

Whitespace cleanup

microsub
J. King 6 jaren geleden
bovenliggende
commit
f64f0c6a22
  1. 8
      dist/nginx.conf
  2. 2
      lib/Arsse.php
  3. 4
      lib/CLI.php
  4. 2
      lib/Conf.php
  5. 72
      lib/Database.php
  6. 2
      lib/Db/AbstractDriver.php
  7. 2
      lib/Db/Driver.php
  8. 2
      lib/Feed.php
  9. 36
      lib/Misc/Context.php
  10. 2
      lib/REST/AbstractHandler.php
  11. 12
      lib/REST/NextCloudNews/V1_2.php
  12. 2
      lib/REST/Target.php
  13. 6
      lib/REST/TinyTinyRSS/API.php
  14. 2
      lib/REST/TinyTinyRSS/Exception.php
  15. 4
      lib/Service.php
  16. 2
      lib/Service/Curl/Driver.php
  17. 4
      lib/Service/Forking/Driver.php
  18. 4
      lib/Service/Internal/Driver.php
  19. 4
      locale/en.php
  20. 4
      sql/SQLite3/0.sql
  21. 4
      tests/cases/Db/SQLite3/TestStatement.php
  22. 2
      tests/cases/Db/SQLite3PDO/TestStatement.php
  23. 8
      tests/cases/Feed/TestFeed.php
  24. 2
      tests/cases/Misc/TestValueInfo.php
  25. 2
      tests/cases/REST/NextCloudNews/TestV1_2.php
  26. 4
      tests/cases/REST/TestREST.php
  27. 34
      tests/cases/REST/TinyTinyRSS/TestAPI.php
  28. 2
      tests/cases/User/TestAuthorization.php
  29. 2
      tests/docroot/Feed/Fetching/Timeout.php
  30. 2
      tests/docroot/Feed/Fetching/TooLarge.php
  31. 2
      tests/docroot/Feed/NextFetch/NotModified.php
  32. 4
      tests/docroot/Feed/Parsing/XXEAttack.php
  33. 4
      tests/lib/Database/SeriesCleanup.php
  34. 2
      tests/lib/Database/SeriesFeed.php
  35. 20
      tests/lib/Database/SeriesUser.php
  36. 8
      www/tt-rss/images/README

8
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;
}
}
}

2
lib/Arsse.php

@ -8,7 +8,7 @@ namespace JKingWeb\Arsse;
class Arsse {
const VERSION = "0.4.0";
/** @var Lang */
public static $lang;
/** @var Conf */

4
lib/CLI.php

@ -8,7 +8,7 @@ namespace JKingWeb\Arsse;
class CLI {
protected $args = [];
protected function usage(): string {
$prog = basename($_SERVER['argv'][0]);
return <<<USAGE_TEXT
@ -21,7 +21,7 @@ Usage:
$prog --help | -h
The Arsse command-line interface currently allows you to start the refresh
daemon, refresh a specific feed by numeric ID, add a user, or save default
daemon, refresh a specific feed by numeric ID, add a user, or save default
configuration to a sample file.
USAGE_TEXT;
}

2
lib/Conf.php

@ -56,7 +56,7 @@ class Conf {
public $serviceCurlUser = null;
/** @var string The password to use when performing feed updates using cURL */
public $serviceCurlPassword = null;
/** @var integer Number of seconds to wait for data when fetching feeds from foreign servers */
public $fetchTimeout = 10;
/** @var integer Maximum size, in bytes, of data when fetching feeds from foreign servers */

72
lib/Database.php

@ -21,7 +21,7 @@ class Database {
const LIST_CONSERVATIVE = 1; // base metadata plus anything that is not potentially large text
const LIST_TYPICAL = 2; // conservative, with the addition of content
const LIST_FULL = 3; // all possible fields
/** @var Db\Driver */
public $db;
@ -37,7 +37,7 @@ class Database {
protected function caller(): string {
return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
}
public static function driverList(): array {
$sep = \DIRECTORY_SEPARATOR;
$path = __DIR__.$sep."Db".$sep;
@ -102,7 +102,7 @@ class Database {
public function metaGet(string $key) {
return $this->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

2
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();

2
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;

2
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);

36
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);
}

2
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)) {

12
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);

2
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);

6
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);

2
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);

4
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);

2
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");
}

4
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() {
}

4
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() {
}

4
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',
];
];

4
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');
insert into arsse_meta(key,value) values('schema_version','1');

4
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));

2
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 = ?

8
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");

2
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],

2
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);

4
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();

34
tests/cases/REST/TinyTinyRSS/TestAPI.php

@ -105,21 +105,21 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
protected $richContent = <<<LONG_STRING
<section>
<p>
<b>Pour</b> 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
<b>Pour</b> 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.
</p>
</section>
@ -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],

2
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, "");

2
tests/docroot/Feed/Fetching/Timeout.php

@ -1,4 +1,4 @@
<?php
<?php
usleep(1.05 * 1000000);
return [
'code' => 404,

2
tests/docroot/Feed/Fetching/TooLarge.php

@ -1,4 +1,4 @@
<?php
<?php
$item = '
<item>
<description>'.str_repeat("0", 1024).'</description>

2
tests/docroot/Feed/NextFetch/NotModified.php

@ -1,4 +1,4 @@
<?php
<?php
if (array_key_exists("t", $_GET)) {
return [
'code' => 304,

4
tests/docroot/Feed/Parsing/XXEAttack.php

@ -1,8 +1,8 @@
<?php return [
'mime' => "application/rss+xml",
'content' => <<<MESSAGE_BODY
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>

4
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();

2
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"));

20
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);

8
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

Laden…
Annuleren
Opslaan