Whitespace cleanup
This commit is contained in:
parent
3fee77bac2
commit
f64f0c6a22
36 changed files with 139 additions and 139 deletions
8
dist/nginx.conf
vendored
8
dist/nginx.conf
vendored
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace JKingWeb\Arsse;
|
|||
|
||||
class Arsse {
|
||||
const VERSION = "0.4.0";
|
||||
|
||||
|
||||
/** @var Lang */
|
||||
public static $lang;
|
||||
/** @var Conf */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
];
|
||||
];
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 = ?
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -16,7 +16,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function setUp() {
|
||||
$this->clearData();
|
||||
}
|
||||
|
||||
|
||||
public function testGetIntegerInfo() {
|
||||
$tests = [
|
||||
[null, I::NULL],
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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, "");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
<?php
|
||||
usleep(1.05 * 1000000);
|
||||
return [
|
||||
'code' => 404,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
<?php
|
||||
$item = '
|
||||
<item>
|
||||
<description>'.str_repeat("0", 1024).'</description>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
<?php
|
||||
if (array_key_exists("t", $_GET)) {
|
||||
return [
|
||||
'code' => 304,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue