From 03495c11ed69f6311e9c7596cc53c5b15ce82bf6 Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 19:59:25 +0000 Subject: Address PHPStan warnings in 'classes/sanitizer.php'. This also includes some minor tweaks to things that call 'Sanitizer::sanitize()'. --- plugins/share/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/share/init.php b/plugins/share/init.php index 359d86802..8da417e52 100644 --- a/plugins/share/init.php +++ b/plugins/share/init.php @@ -133,7 +133,7 @@ class Share extends Plugin { $line["content"] = Sanitizer::sanitize($line["content"], $line['hide_images'], - $owner_uid, $line["site_url"], false, $line["id"]); + $owner_uid, $line["site_url"], null, $line["id"]); PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_RENDER_ARTICLE, function ($result) use (&$line) { -- cgit v1.2.3-54-g00ecf From 68d7cf44f994b422ede2adc6d182d5efce5cbe64 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sat, 13 Nov 2021 19:49:37 +0300 Subject: phpstan: deal with plugins/share --- plugins/share/init.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/share/init.php b/plugins/share/init.php index 8da417e52..4a2a942d7 100644 --- a/plugins/share/init.php +++ b/plugins/share/init.php @@ -1,14 +1,16 @@ */ function about() { return array(null, "Share article by unique URL", "fox"); } - /* @var PluginHost $host */ + /** @param PluginHost $host */ function init($host) { $this->host = $host; @@ -20,18 +22,22 @@ class Share extends Plugin { return $method == "get"; } + /** @return string */ function get_js() { return file_get_contents(__DIR__ . "/share.js"); } + /** @return string */ function get_css() { return file_get_contents(__DIR__ . "/share.css"); } + /** @return string */ function get_prefs_js() { return file_get_contents(__DIR__ . "/share_prefs.js"); } + /** @return void */ function unshare() { $id = $_REQUEST['id']; @@ -42,6 +48,9 @@ class Share extends Plugin { print __("Article unshared"); } + /** @param int $id + * + * @return void */ function hook_prefs_tab_section($id) { if ($id == "prefFeedsPublishedGenerated") { ?> @@ -56,6 +65,7 @@ class Share extends Plugin { } } + /** @return void */ function clearArticleKeys() { $sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET uuid = '' WHERE owner_uid = ?"); @@ -64,6 +74,7 @@ class Share extends Plugin { print __("Shared URLs cleared."); } + /** @return void */ function newkey() { $id = $_REQUEST['id']; $uuid = uniqid_short(); @@ -75,6 +86,10 @@ class Share extends Plugin { print json_encode(["link" => $uuid]); } + /** + * @param array $line + * + * @return string */ function hook_article_button($line) { $icon_class = !empty($line['uuid']) ? "is-shared" : ""; @@ -83,6 +98,7 @@ class Share extends Plugin { title='".__('Share by URL')."'>link"; } + /** @return void */ function get() { $uuid = clean($_REQUEST["key"] ?? ""); @@ -107,7 +123,7 @@ class Share extends Plugin { print "Article not found."; } - private function format_article($id, $owner_uid) { + private function format_article(int $id, int $owner_uid) : void { $pdo = Db::pdo(); @@ -231,6 +247,7 @@ class Share extends Plugin { } } + /** @return void */ function shareDialog() { $id = (int)clean($_REQUEST['id'] ?? 0); @@ -276,6 +293,7 @@ class Share extends Plugin { Date: Sat, 13 Nov 2021 19:52:47 +0300 Subject: no need to duplicate annotations --- classes/plugin.php | 7 ++++++- plugins/share/init.php | 5 ----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/classes/plugin.php b/classes/plugin.php index 5b486d766..eae2c0c17 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -12,7 +12,7 @@ abstract class Plugin { * */ abstract function init($host); - /** @return array */ + /** @return array */ abstract function about(); // return array(1.0, "plugin", "No description", "No author", false); @@ -49,6 +49,11 @@ abstract class Plugin { return ""; } + /** @return string */ + function get_css() { + return ""; + } + /** @return string */ function get_prefs_js() { return ""; diff --git a/plugins/share/init.php b/plugins/share/init.php index 4a2a942d7..4dbc389fd 100644 --- a/plugins/share/init.php +++ b/plugins/share/init.php @@ -3,14 +3,12 @@ class Share extends Plugin { /** @var PluginHost $host */ private $host; - /** @return array */ function about() { return array(null, "Share article by unique URL", "fox"); } - /** @param PluginHost $host */ function init($host) { $this->host = $host; @@ -22,17 +20,14 @@ class Share extends Plugin { return $method == "get"; } - /** @return string */ function get_js() { return file_get_contents(__DIR__ . "/share.js"); } - /** @return string */ function get_css() { return file_get_contents(__DIR__ . "/share.css"); } - /** @return string */ function get_prefs_js() { return file_get_contents(__DIR__ . "/share_prefs.js"); } -- cgit v1.2.3-54-g00ecf From 618e96b793769ef4d7912f1f16f1ca7436acd199 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sat, 13 Nov 2021 19:55:30 +0300 Subject: deal with some warnings in plugins/trgm,readability and base plugin class --- classes/plugin.php | 2 +- plugins/af_psql_trgm/init.php | 8 +++++++- plugins/af_readability/init.php | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/classes/plugin.php b/classes/plugin.php index eae2c0c17..ea79e6a65 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -20,7 +20,7 @@ abstract class Plugin { $this->pdo = Db::pdo(); } - /** @return array */ + /** @return array */ function flags() { /* associative array, possible keys: needs_curl = boolean diff --git a/plugins/af_psql_trgm/init.php b/plugins/af_psql_trgm/init.php index 87415450b..aea24fea7 100644 --- a/plugins/af_psql_trgm/init.php +++ b/plugins/af_psql_trgm/init.php @@ -1,9 +1,13 @@ true); } + /** @return void */ function save() { $enable_share_anything = checkbox_to_sql_bool($_POST["enable_share_anything"] ?? ""); -- cgit v1.2.3-54-g00ecf From fe5ada72504705f9304c3f0bba049a20998fe650 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sat, 13 Nov 2021 20:07:13 +0300 Subject: set some annotations on Plugin hook methods --- classes/plugin.php | 17 +++++++++++++++++ plugins/share/init.php | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/classes/plugin.php b/classes/plugin.php index feae9ec9c..638cc2f50 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -96,22 +96,39 @@ abstract class Plugin { /* plugin hook methods */ + /** + * @param array $line + * @return string + */ function hook_article_button($line) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param array $article + * @return array + */ function hook_article_filter($article) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param string $tab + * @return void + */ function hook_prefs_tab($tab) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param string $section + * @return void + */ function hook_prefs_tab_section($section) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** @return void */ function hook_prefs_tabs() { user_error("Dummy method invoked.", E_USER_ERROR); } diff --git a/plugins/share/init.php b/plugins/share/init.php index 4dbc389fd..b900de5c0 100644 --- a/plugins/share/init.php +++ b/plugins/share/init.php @@ -43,8 +43,8 @@ class Share extends Plugin { print __("Article unshared"); } - /** @param int $id - * + /** + * @param string $id * @return void */ function hook_prefs_tab_section($id) { if ($id == "prefFeedsPublishedGenerated") { -- cgit v1.2.3-54-g00ecf From 81a10f69bcc38b62aad79f9be716adcf4ed49d2d Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 10:48:32 +0300 Subject: deal with phpstan warnings related to base authentication modules --- classes/auth/base.php | 1 - classes/iauthmodule.php | 13 ++++++++++++- classes/plugin.php | 18 +++++++++++++++++- plugins/auth_internal/init.php | 1 + 4 files changed, 30 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/classes/auth/base.php b/classes/auth/base.php index 82ea06e1b..939a9d358 100644 --- a/classes/auth/base.php +++ b/classes/auth/base.php @@ -8,7 +8,6 @@ abstract class Auth_Base extends Plugin implements IAuthModule { $this->pdo = Db::pdo(); } - // compatibility wrapper, because of how pluginhost works (hook name == method name) function hook_auth_user(...$args) { return $this->authenticate(...$args); } diff --git a/classes/iauthmodule.php b/classes/iauthmodule.php index e714cc6ca..39aae4cc2 100644 --- a/classes/iauthmodule.php +++ b/classes/iauthmodule.php @@ -1,5 +1,16 @@ authenticate(...$args) (Auth_Base) + * @param mixed $args = ($login, $password, $service) + * @return int|false user_id + */ + function hook_auth_user(...$args); } diff --git a/classes/plugin.php b/classes/plugin.php index 638cc2f50..bcd8c0de7 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -141,8 +141,24 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } - function hook_auth_user($login, $password, $service) { + /** this is a pluginhost compatibility wrapper that invokes $this->authenticate(...$args) (Auth_Base) + * @param mixed $args = ($login, $password, $service) + * @return int|false user_id + */ + function hook_auth_user(...$args) { user_error("Dummy method invoked.", E_USER_ERROR); + return false; + } + + /** IAuthModule only + * @param string $login + * @param string $password + * optional third string $service + * @return int|false user_id + */ + function authenticate($login, $password) { + user_error("Dummy method invoked.", E_USER_ERROR); + return false; } function hook_hotkey_map($hotkeys) { diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php index 77f7596f0..b66f7719b 100644 --- a/plugins/auth_internal/init.php +++ b/plugins/auth_internal/init.php @@ -12,6 +12,7 @@ class Auth_Internal extends Auth_Base { $host->add_hook($host::HOOK_AUTH_USER, $this); } + /** @param string $service */ function authenticate($login, $password, $service = '') { $otp = (int) ($_REQUEST["otp"] ?? 0); -- cgit v1.2.3-54-g00ecf From 0a2dcacbcf01e1ebb225570fb99811c4215c6ea9 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 11:11:49 +0300 Subject: normalize some mismatching hook function definitions to match base Plugin class --- classes/auth/base.php | 4 ++-- classes/iauthmodule.php | 10 ++++++---- classes/plugin.php | 27 +++++++++++++++++++++------ plugins/af_youtube_embed/init.php | 2 +- plugins/auth_remote/init.php | 2 +- plugins/cache_starred_images/init.php | 2 +- plugins/no_iframes/init.php | 2 +- 7 files changed, 33 insertions(+), 16 deletions(-) (limited to 'plugins') diff --git a/classes/auth/base.php b/classes/auth/base.php index 939a9d358..9950cbf07 100644 --- a/classes/auth/base.php +++ b/classes/auth/base.php @@ -8,8 +8,8 @@ abstract class Auth_Base extends Plugin implements IAuthModule { $this->pdo = Db::pdo(); } - function hook_auth_user(...$args) { - return $this->authenticate(...$args); + function hook_auth_user($login, $password, $service = '') { + return $this->authenticate($login, $password, $service); } // Auto-creates specified user if allowed by system configuration diff --git a/classes/iauthmodule.php b/classes/iauthmodule.php index 39aae4cc2..dbf8c5587 100644 --- a/classes/iauthmodule.php +++ b/classes/iauthmodule.php @@ -3,14 +3,16 @@ interface IAuthModule { /** * @param string $login * @param string $password - * optional third string $service + * @param string $service * @return int|false user_id */ - function authenticate($login, $password); // + optional third parameter: $service + function authenticate($login, $password, $service = ''); /** this is a pluginhost compatibility wrapper that invokes $this->authenticate(...$args) (Auth_Base) - * @param mixed $args = ($login, $password, $service) + * @param string $login + * @param string $password + * @param string $service * @return int|false user_id */ - function hook_auth_user(...$args); + function hook_auth_user($login, $password, $service = ''); } diff --git a/classes/plugin.php b/classes/plugin.php index bcd8c0de7..8c14cd78d 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -1,4 +1,11 @@ authenticate(...$args) (Auth_Base) - * @param mixed $args = ($login, $password, $service) + * @param string $login + * @param string $password + * @param string $service * @return int|false user_id */ - function hook_auth_user(...$args) { + function hook_auth_user($login, $password, $service = '') { user_error("Dummy method invoked.", E_USER_ERROR); return false; } @@ -153,10 +162,10 @@ abstract class Plugin { /** IAuthModule only * @param string $login * @param string $password - * optional third string $service + * @param string $service * @return int|false user_id */ - function authenticate($login, $password) { + function authenticate($login, $password, $service = '') { user_error("Dummy method invoked.", E_USER_ERROR); return false; } @@ -257,6 +266,12 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param array $entry + * @param int $id + * @param array{'formatted': string, 'entries': array>} $rv + * @return array + */ function hook_enclosure_entry($entry, $id, $rv) { user_error("Dummy method invoked.", E_USER_ERROR); } @@ -289,7 +304,7 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } - function hook_article_image($enclosures, $content, $site_url) { + function hook_article_image($enclosures, $content, $site_url, $article) { user_error("Dummy method invoked.", E_USER_ERROR); } @@ -317,7 +332,7 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } - function hook_pre_subscribe($url, $auth_login, $auth_pass) { + function hook_pre_subscribe(&$url, $auth_login, $auth_pass) { user_error("Dummy method invoked.", E_USER_ERROR); } } diff --git a/plugins/af_youtube_embed/init.php b/plugins/af_youtube_embed/init.php index 771ee8c46..a1be5562a 100644 --- a/plugins/af_youtube_embed/init.php +++ b/plugins/af_youtube_embed/init.php @@ -18,7 +18,7 @@ class Af_Youtube_Embed extends Plugin { "youtu.be"]); } - function hook_render_enclosure($entry, $hide_images) { + function hook_render_enclosure($entry, $id, $rv) { $url = $entry["content_url"]; diff --git a/plugins/auth_remote/init.php b/plugins/auth_remote/init.php index b240a9402..35ee9e31d 100644 --- a/plugins/auth_remote/init.php +++ b/plugins/auth_remote/init.php @@ -29,7 +29,7 @@ class Auth_Remote extends Auth_Base { return ""; } - function authenticate($login, $password) { + function authenticate($login, $password, $service = '') { $try_login = ""; foreach (["REMOTE_USER", "HTTP_REMOTE_USER", "REDIRECT_REMOTE_USER", "PHP_AUTH_USER"] as $hdr) { diff --git a/plugins/cache_starred_images/init.php b/plugins/cache_starred_images/init.php index d94e60504..36e8b73f0 100755 --- a/plugins/cache_starred_images/init.php +++ b/plugins/cache_starred_images/init.php @@ -97,7 +97,7 @@ class Cache_Starred_Images extends Plugin { } } - function hook_enclosure_entry($enc, $article_id) { + function hook_enclosure_entry($enc, $article_id, $rv) { $local_filename = $article_id . "-" . sha1($enc["content_url"]); if ($this->cache->exists($local_filename)) { diff --git a/plugins/no_iframes/init.php b/plugins/no_iframes/init.php index 3cfa15915..dc297b60e 100644 --- a/plugins/no_iframes/init.php +++ b/plugins/no_iframes/init.php @@ -11,7 +11,7 @@ class No_Iframes extends Plugin { $host->add_hook($host::HOOK_SANITIZE, $this); } - function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes) { + function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes, $article_id) { $xpath = new DOMXpath($doc); $entries = $xpath->query('//iframe'); -- cgit v1.2.3-54-g00ecf From dd7299b6d070d26ff97194ef14be349f08776e2a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 17:19:35 +0300 Subject: deal with a few more phpstan warnings re: base plugin class --- classes/plugin.php | 48 ++++++++++++++++++++++++++++++++++++++++- plugins/af_readability/init.php | 1 + 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/classes/plugin.php b/classes/plugin.php index 96541d033..ac234f081 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -226,8 +226,18 @@ abstract class Plugin { return ""; } + /** + * @param DOMDocument $doc + * @param string $site_url + * @param array $allowed_elements + * @param array $disallowed_attributes + * @param int $article_id + * @return DOMDocument + */ function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes, $article_id) { user_error("Dummy method invoked.", E_USER_ERROR); + + return $doc; } /** @@ -301,8 +311,20 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param string $feed_data + * @param string $fetch_url + * @param int $owner_uid + * @param int $feed + * @param int $last_article_timestamp + * @param string $auth_login + * @param string $auth_pass + * @return string (possibly mangled feed data) + */ function hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed, $last_article_timestamp, $auth_login, $auth_pass) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } /** @@ -331,8 +353,19 @@ abstract class Plugin { return []; } - function hook_format_enclosures($rv, $result, $id, $always_display_enclosures, $article_content, $hide_images) { + /** + * @param string $enclosures_formatted + * @param array> $enclosures + * @param int $article_id + * @param bool $always_display_enclosures + * @param string $article_content + * @param bool $hide_images + * @return string|array>> ($enclosures_formatted, $enclosures) + */ + function hook_format_enclosures($enclosures_formatted, $enclosures, $article_id, $always_display_enclosures, $article_content, $hide_images) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } /** @@ -344,6 +377,8 @@ abstract class Plugin { */ function hook_subscribe_feed($contents, $url, $auth_login, $auth_pass) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } /** @@ -366,10 +401,19 @@ abstract class Plugin { */ function hook_render_enclosure($entry, $article_id, $rv) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** + * @param array $article + * @param string $action + * @return array ($article) + */ function hook_article_filter_action($article, $action) { user_error("Dummy method invoked.", E_USER_ERROR); + + return []; } /** @@ -409,6 +453,8 @@ abstract class Plugin { */ function hook_format_article($html, $row) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } function hook_feed_basic_info($basic_info, $fetch_url, $owner_uid, $feed_id, $auth_login, $auth_pass) { diff --git a/plugins/af_readability/init.php b/plugins/af_readability/init.php index 05b229eae..8e75d0c2e 100755 --- a/plugins/af_readability/init.php +++ b/plugins/af_readability/init.php @@ -187,6 +187,7 @@ class Af_Readability extends Plugin { case "action_append": return $this->process_article($article, true); } + return $article; } public function extract_content($url) { -- cgit v1.2.3-54-g00ecf From 01b39d985c9f194a35c690a18149cbb06fc7b0d3 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 18:00:03 +0300 Subject: deal with the rest of warnings in plugin.php --- classes/plugin.php | 55 ++++++++++++++++++++++++++++++++++++++++++++++ plugins/af_comics/init.php | 1 + 2 files changed, 56 insertions(+) (limited to 'plugins') diff --git a/classes/plugin.php b/classes/plugin.php index ac234f081..b20bbcbc2 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -457,16 +457,40 @@ abstract class Plugin { return ""; } + /** + * @param array{"title": string, "site_url": string} $basic_info + * @param string $fetch_url + * @param int $owner_uid + * @param int $feed_id + * @param string $auth_login + * @param string $auth_pass + * @return array{"title": string, "site_url": string} + */ function hook_feed_basic_info($basic_info, $fetch_url, $owner_uid, $feed_id, $auth_login, $auth_pass) { user_error("Dummy method invoked.", E_USER_ERROR); + + return $basic_info; } + /** + * @param string $filename + * @return bool + */ function hook_send_local_file($filename) { user_error("Dummy method invoked.", E_USER_ERROR); + + return false; } + /** + * @param int $feed_id + * @param int $owner_uid + * @return bool + */ function hook_unsubscribe_feed($feed_id, $owner_uid) { user_error("Dummy method invoked.", E_USER_ERROR); + + return false; } /** @@ -533,23 +557,54 @@ abstract class Plugin { return false; } + /** + * @param array $enclosure + * @param int $feed + * @return array ($enclosure) + */ function hook_enclosure_imported($enclosure, $feed) { user_error("Dummy method invoked.", E_USER_ERROR); + + return $enclosure; } + /** @return array */ function hook_headlines_custom_sort_map() { user_error("Dummy method invoked.", E_USER_ERROR); + + return ["" => ""]; } + /** + * @param string $order + * @return array -- query, skip_first_id + */ function hook_headlines_custom_sort_override($order) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ["", false]; } + /** + * @param int $feed_id + * @param int $is_cat + * @return string + */ function hook_headline_toolbar_select_menu_item($feed_id, $is_cat) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** + * @param string $url + * @param string $auth_login + * @param string $auth_pass + * @return bool + */ function hook_pre_subscribe(&$url, $auth_login, $auth_pass) { user_error("Dummy method invoked.", E_USER_ERROR); + + return false; } } diff --git a/plugins/af_comics/init.php b/plugins/af_comics/init.php index 84d95a2ba..a9a8f3faa 100755 --- a/plugins/af_comics/init.php +++ b/plugins/af_comics/init.php @@ -1,6 +1,7 @@ $filters */ private $filters = array(); function about() { -- cgit v1.2.3-54-g00ecf From 6bd6a14c207ddaf35256b11dd381093d57ef38a4 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 20:19:12 +0300 Subject: revise phpdoc annotations for hook_sanitize() --- classes/plugin.php | 4 ++-- plugins/af_youtube_embed/init.php | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/classes/plugin.php b/classes/plugin.php index 290c4cc3b..55ccff9c3 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -232,7 +232,7 @@ abstract class Plugin { * @param array $allowed_elements * @param array $disallowed_attributes * @param int $article_id - * @return DOMDocument + * @return DOMDocument|array> */ function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes, $article_id) { user_error("Dummy method invoked.", E_USER_ERROR); @@ -519,7 +519,7 @@ abstract class Plugin { /** * @param string $url - * @return string + * @return string|false */ function hook_get_full_text($url) { user_error("Dummy method invoked.", E_USER_ERROR); diff --git a/plugins/af_youtube_embed/init.php b/plugins/af_youtube_embed/init.php index a1be5562a..ff44bb291 100644 --- a/plugins/af_youtube_embed/init.php +++ b/plugins/af_youtube_embed/init.php @@ -32,6 +32,8 @@ class Af_Youtube_Embed extends Plugin { "; } + + return ""; } function api_version() { -- cgit v1.2.3-54-g00ecf From d17b79311e9c80576a8bf392b9d1dbee7fa8fbdc Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 20:33:37 +0300 Subject: set missing annotations in af_comics --- plugins/af_comics/filter_base.php | 18 ++++++++++++++++++ plugins/af_comics/filters/af_comics_tfd.php | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/af_comics/filter_base.php b/plugins/af_comics/filter_base.php index 5c82bc870..83bc48184 100644 --- a/plugins/af_comics/filter_base.php +++ b/plugins/af_comics/filter_base.php @@ -1,20 +1,38 @@ */ public abstract function supported(); + + /** + * @param array $article + * @return bool + */ public abstract function process(&$article); public function __construct(/*PluginHost $host*/) { } + /** + * @param string $url + * @return string|false + */ public function on_subscribe($url) { return false; } + /** + * @param string $url + * @return array{"title": string, "site_url": string}|false + */ public function on_basic_info($url) { return false; } + /** + * @param string $url + * @return string|false + */ public function on_fetch($url) { return false; } diff --git a/plugins/af_comics/filters/af_comics_tfd.php b/plugins/af_comics/filters/af_comics_tfd.php index 19ca43a24..2010da37e 100644 --- a/plugins/af_comics/filters/af_comics_tfd.php +++ b/plugins/af_comics/filters/af_comics_tfd.php @@ -12,7 +12,7 @@ class Af_Comics_Tfd extends Af_ComicFilter { false, false, 0, "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"); - if (!$res) return $article; + if (!$res) return false; $doc = new DOMDocument(); -- cgit v1.2.3-54-g00ecf From cfc31fc692d34a61ec1974e2c159efebf6b511be Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 20:36:55 +0300 Subject: set annotations/types in af_psql_trgm --- plugins/af_psql_trgm/init.php | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'plugins') diff --git a/plugins/af_psql_trgm/init.php b/plugins/af_psql_trgm/init.php index aea24fea7..89b66e20b 100644 --- a/plugins/af_psql_trgm/init.php +++ b/plugins/af_psql_trgm/init.php @@ -202,7 +202,7 @@ class Af_Psql_Trgm extends Plugin { filter_unknown_feeds( - $this->get_stored_array("enabled_feeds")); + $this->host->get_array($this, "enabled_feeds")); $this->host->set($this, "enabled_feeds", $enabled_feeds); ?> @@ -227,7 +227,7 @@ class Af_Psql_Trgm extends Plugin { } function hook_prefs_edit_feed($feed_id) { - $enabled_feeds = $this->get_stored_array("enabled_feeds"); + $enabled_feeds = $this->host->get_array($this, "enabled_feeds"); ?>
@@ -244,7 +244,7 @@ class Af_Psql_Trgm extends Plugin { } function hook_prefs_save_feed($feed_id) { - $enabled_feeds = $this->get_stored_array("enabled_feeds"); + $enabled_feeds = $this->host->get_array($this, "enabled_feeds"); $enable = checkbox_to_sql_bool($_POST["trgm_similarity_enabled"] ?? ""); $key = array_search($feed_id, $enabled_feeds); @@ -273,7 +273,7 @@ class Af_Psql_Trgm extends Plugin { if (!$enable_globally && !in_array($article["feed"]["id"], - $this->get_stored_array("enabled_feeds"))) { + $this->host->get_array($this,"enabled_feeds"))) { return $article; } @@ -281,14 +281,14 @@ class Af_Psql_Trgm extends Plugin { $similarity = (float) $this->host->get($this, "similarity", $this->default_similarity); if ($similarity < 0.01) { - Debug::log("af_psql_trgm: similarity is set too low ($similarity)", Debug::$LOG_EXTENDED); + Debug::log("af_psql_trgm: similarity is set too low ($similarity)", Debug::LOG_EXTENDED); return $article; } $min_title_length = (int) $this->host->get($this, "min_title_length", $this->default_min_length); if (mb_strlen($article["title"]) < $min_title_length) { - Debug::log("af_psql_trgm: article title is too short (min: $min_title_length)", Debug::$LOG_EXTENDED); + Debug::log("af_psql_trgm: article title is too short (min: $min_title_length)", Debug::LOG_EXTENDED); return $article; } @@ -327,10 +327,10 @@ class Af_Psql_Trgm extends Plugin { $row = $sth->fetch(); $similarity_result = $row['ms']; - Debug::log("af_psql_trgm: similarity result for $title_escaped: $similarity_result", Debug::$LOG_EXTENDED); + Debug::log("af_psql_trgm: similarity result for $title_escaped: $similarity_result", Debug::LOG_EXTENDED); if ($similarity_result >= $similarity) { - Debug::log("af_psql_trgm: marking article as read ($similarity_result >= $similarity)", Debug::$LOG_EXTENDED); + Debug::log("af_psql_trgm: marking article as read ($similarity_result >= $similarity)", Debug::LOG_EXTENDED); $article["force_catchup"] = true; } @@ -342,7 +342,12 @@ class Af_Psql_Trgm extends Plugin { return 2; } - private function filter_unknown_feeds($enabled_feeds) { + /** + * @param array $enabled_feeds + * @return array + * @throws PDOException + */ + private function filter_unknown_feeds($enabled_feeds) : array { $tmp = array(); foreach ($enabled_feeds as $feed) { @@ -357,14 +362,4 @@ class Af_Psql_Trgm extends Plugin { return $tmp; } - - private function get_stored_array($name) { - $tmp = $this->host->get($this, $name); - - if (!is_array($tmp)) $tmp = []; - - return $tmp; - } - - } -- cgit v1.2.3-54-g00ecf From 80291ffe0c3b43858cf9db3e5ffe5470259503ac Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 20:51:22 +0300 Subject: deal with phpstan warnings in plugins/af_redditimgur.php --- plugins/af_redditimgur/init.php | 80 +++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 22 deletions(-) (limited to 'plugins') diff --git a/plugins/af_redditimgur/init.php b/plugins/af_redditimgur/init.php index bd4032050..aeb75df3a 100755 --- a/plugins/af_redditimgur/init.php +++ b/plugins/af_redditimgur/init.php @@ -3,10 +3,20 @@ class Af_RedditImgur extends Plugin { /** @var PluginHost $host */ private $host; + + /** @var array */ private $domain_blacklist = [ "github.com" ]; + + /** @var bool */ private $dump_json_data = false; + + /** @var array */ private $fallback_preview_urls = []; + + /** @var int */ private $default_max_score = 100; + + /** @var array> */ private $generated_enclosures = []; function about() { @@ -118,7 +128,7 @@ class Af_RedditImgur extends Plugin { $data (this is a huge blob of random crap returned by reddit API) + * @param DOMDocument $doc + * @param DOMXPath $xpath + * @param DOMElement $anchor + * @return bool + */ + private function process_post_media(array $data, DOMDocument $doc, DOMXPath $xpath, DOMElement $anchor) : bool { $found = 0; if (isset($data["media_metadata"])) { @@ -242,14 +259,21 @@ class Af_RedditImgur extends Plugin { } } - return $found; + return $found > 0; } /* function score_convert(int $value, int $from1, int $from2, int $to1, int $to2) { return ($value - $from1) / ($from2 - $from1) * ($to2 - $to1) + $to1; } */ - private function inline_stuff(&$article, &$doc, $xpath) { + /** + * @param array $article + * @param DOMDocument $doc + * @param DOMXPath $xpath + * @return bool + * @throws PDOException + */ + private function inline_stuff(array &$article, DOMDocument &$doc, DOMXpath $xpath) : bool { $max_score = (int) $this->host->get($this, "max_score", $this->default_max_score); $import_score = (bool) $this->host->get($this, "import_score", $this->default_max_score); @@ -263,7 +287,7 @@ class Af_RedditImgur extends Plugin { $this->generated_enclosures = []; - // embed anchor element, before reddit post layout + /** @var DOMElement|false $anchor -- embed anchor element, before reddit
post layout */ $anchor = $xpath->query('//body/*')->item(0); // deal with json-provided media content first @@ -583,7 +607,7 @@ class Af_RedditImgur extends Plugin { if ($found) $this->remove_post_thumbnail($doc, $xpath); - return $found; + return $found > 0; } function hook_article_filter($article) { @@ -651,14 +675,14 @@ class Af_RedditImgur extends Plugin { return 2; } - private function remove_post_thumbnail($doc, $xpath) { + private function remove_post_thumbnail(DOMDocument $doc, DOMXpath $xpath) : void { $thumb = $xpath->query("//td/a/img[@src]")->item(0); if ($thumb) $thumb->parentNode->parentNode->removeChild($thumb->parentNode); } - private function handle_as_image($doc, $entry, $image_url, $link_url = false) { + private function handle_as_image(DOMDocument $doc, DOMElement $entry, string $image_url, string $link_url = "") : void { $img = $doc->createElement("img"); $img->setAttribute("src", $image_url); @@ -677,7 +701,7 @@ class Af_RedditImgur extends Plugin { $entry->parentNode->insertBefore($p, $entry); } - private function handle_as_video($doc, $entry, $source_stream, $poster_url = false) { + private function handle_as_video(DOMDocument $doc, DOMElement $entry, string $source_stream, string $poster_url = "") : void { Debug::log("handle_as_video: $source_stream", Debug::LOG_VERBOSE); @@ -709,7 +733,7 @@ class Af_RedditImgur extends Plugin { return $method === "testurl"; } - function testurl() { + function testurl() : void { $url = clean($_POST["url"] ?? ""); $article_url = clean($_POST["article_url"] ?? ""); @@ -804,8 +828,8 @@ class Af_RedditImgur extends Plugin { } /** $useragent defaults to Config::get_user_agent() */ - private function get_header($url, $header, $useragent = false) { - $ret = false; + private function get_header(string $url, int $header, string $useragent = "") : string { + $ret = ""; if (function_exists("curl_init")) { $ch = curl_init($url); @@ -823,16 +847,24 @@ class Af_RedditImgur extends Plugin { return $ret; } - private function get_content_type($url, $useragent = false) { + private function get_content_type(string $url, string $useragent = "") : string { return $this->get_header($url, CURLINFO_CONTENT_TYPE, $useragent); } - // @phpstan-ignore-next-line - private function get_location($url, $useragent = false) { + /*private function get_location(string $url, string $useragent = "") : string { return $this->get_header($url, CURLINFO_EFFECTIVE_URL, $useragent); - } - - private function readability($article, $url, $doc, $xpath, $debug = false) { + }*/ + + /** + * @param array $article + * @param string $url + * @param DOMDocument $doc + * @param DOMXPath $xpath + * @param bool $debug + * @return array + * @throws PDOException + */ + private function readability(array $article, string $url, DOMDocument $doc, DOMXpath $xpath, bool $debug = false) : array { if (function_exists("curl_init") && $this->host->get($this, "enable_readability") && mb_strlen(strip_tags($article["content"])) <= 150) { @@ -864,7 +896,12 @@ class Af_RedditImgur extends Plugin { return $article; } - private function is_blacklisted($src, $also_blacklist = []) { + /** + * @param string $src + * @param array $also_blacklist + * @return bool + */ + private function is_blacklisted(string $src, array $also_blacklist = []) : bool { $src_domain = parse_url($src, PHP_URL_HOST); foreach (array_merge($this->domain_blacklist, $also_blacklist) as $domain) { @@ -880,7 +917,7 @@ class Af_RedditImgur extends Plugin { return $this->hook_render_article_cdm($article); } - private function rewrite_to_teddit($str) { + private function rewrite_to_teddit(string $str) : string { if (strpos($str, "reddit.com") !== false) { return preg_replace("/https?:\/\/([a-z]+\.)?reddit\.com/", "https://teddit.net", $str); } @@ -888,7 +925,7 @@ class Af_RedditImgur extends Plugin { return $str; } - private function rewrite_to_reddit($str) { + private function rewrite_to_reddit(string $str) : string { if (strpos($str, "teddit.net") !== false) { $str = preg_replace("/https?:\/\/teddit.net/", "https://reddit.com", $str); @@ -899,7 +936,6 @@ class Af_RedditImgur extends Plugin { return $str; } - function hook_render_article_cdm($article) { if ($this->host->get($this, "reddit_to_teddit")) { $need_saving = false; -- cgit v1.2.3-54-g00ecf From 91c9a735327ba04fd1e10f81dfca288ae11d779d Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 20:59:49 +0300 Subject: deal with phpstan warnings in plugins/cache_starred_images.php --- plugins/cache_starred_images/init.php | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'plugins') diff --git a/plugins/cache_starred_images/init.php b/plugins/cache_starred_images/init.php index 36e8b73f0..731007b5b 100755 --- a/plugins/cache_starred_images/init.php +++ b/plugins/cache_starred_images/init.php @@ -1,11 +1,14 @@ host->get_owner_uid() . "..."); @@ -53,7 +56,7 @@ class Cache_Starred_Images extends Plugin { $usth = $this->pdo->prepare("UPDATE ttrss_entries SET plugin_data = ? WHERE id = ?"); while ($line = $sth->fetch()) { - Debug::log("processing article " . $line["title"], Debug::$LOG_VERBOSE); + Debug::log("processing article " . $line["title"], Debug::LOG_VERBOSE); if ($line["site_url"]) { $success = $this->cache_article_images($line["content"], $line["site_url"], $line["owner_uid"], $line["id"]); @@ -115,7 +118,7 @@ class Cache_Starred_Images extends Plugin { foreach ($entries as $entry) { if ($entry->hasAttribute('src')) { - $src = rewrite_relative_url($site_url, $entry->getAttribute('src')); + $src = UrlHelper::rewrite_relative($site_url, $entry->getAttribute('src')); $local_filename = $article_id . "-" . sha1($src); @@ -130,11 +133,11 @@ class Cache_Starred_Images extends Plugin { return $doc; } - private function cache_url($article_id, $url) { + private function cache_url(int $article_id, string $url) : bool { $local_filename = $article_id . "-" . sha1($url); if (!$this->cache->exists($local_filename)) { - Debug::log("cache_images: downloading: $url to $local_filename", Debug::$LOG_VERBOSE); + Debug::log("cache_images: downloading: $url to $local_filename", Debug::LOG_VERBOSE); $data = UrlHelper::fetch(["url" => $url, "max_size" => Config::get(Config::MAX_CACHE_FILE_SIZE)]); @@ -150,16 +153,16 @@ class Cache_Starred_Images extends Plugin { return false; } - private function cache_article_images($content, $site_url, $owner_uid, $article_id) { + private function cache_article_images(string $content, string $site_url, int $owner_uid, int $article_id) : bool { $status_filename = $article_id . "-" . sha1($site_url) . ".status"; /* housekeeping might run as a separate user, in this case status/media might not be writable */ if (!$this->cache->is_writable($status_filename)) { - Debug::log("status not writable: $status_filename", Debug::$LOG_VERBOSE); + Debug::log("status not writable: $status_filename", Debug::LOG_VERBOSE); return false; } - Debug::log("status: $status_filename", Debug::$LOG_VERBOSE); + Debug::log("status: $status_filename", Debug::LOG_VERBOSE); if ($this->cache->exists($status_filename)) $status = json_decode($this->cache->get($status_filename), true); @@ -170,7 +173,7 @@ class Cache_Starred_Images extends Plugin { // only allow several download attempts for article if ($status["attempt"] > $this->max_cache_attempts) { - Debug::log("too many attempts for $site_url", Debug::$LOG_VERBOSE); + Debug::log("too many attempts for $site_url", Debug::LOG_VERBOSE); return false; } @@ -194,7 +197,7 @@ class Cache_Starred_Images extends Plugin { $has_images = true; - $src = rewrite_relative_url($site_url, $entry->getAttribute('src')); + $src = UrlHelper::rewrite_relative($site_url, $entry->getAttribute('src')); if ($this->cache_url($article_id, $src)) { $success = true; @@ -210,7 +213,7 @@ class Cache_Starred_Images extends Plugin { while ($enc = $esth->fetch()) { $has_images = true; - $url = rewrite_relative_url($site_url, $enc["content_url"]); + $url = UrlHelper::rewrite_relative($site_url, $enc["content_url"]); if ($this->cache_url($article_id, $url)) { $success = true; -- cgit v1.2.3-54-g00ecf From f537502fce498118543d47b3d1cb463104f25b1d Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 21:09:53 +0300 Subject: deal with (most of) phpstan warnings in auth_internal and auth_remote --- plugins/auth_internal/init.php | 22 +++++++++++++++++++--- plugins/auth_remote/init.php | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php index b66f7719b..1bf3d6a24 100644 --- a/plugins/auth_internal/init.php +++ b/plugins/auth_internal/init.php @@ -130,7 +130,7 @@ class Auth_Internal extends Auth_Base { } if ($login) { - $try_user_id = $this->find_user_by_login($login); + $try_user_id = UserHelper::find_user_by_login($login); if ($try_user_id) { return $this->check_password($try_user_id, $password); @@ -140,6 +140,14 @@ class Auth_Internal extends Auth_Base { return false; } + /** + * @param int $owner_uid + * @param string $password + * @param string $service + * @return int|false (false if failed, user id otherwise) + * @throws PDOException + * @throws Exception + */ function check_password(int $owner_uid, string $password, string $service = '') { $user = ORM::for_table('ttrss_users')->find_one($owner_uid); @@ -203,7 +211,7 @@ class Auth_Internal extends Auth_Base { return false; } - function change_password($owner_uid, $old_password, $new_password) { + function change_password(int $owner_uid, string $old_password, string $new_password) : string { if ($this->check_password($owner_uid, $old_password)) { @@ -246,7 +254,15 @@ class Auth_Internal extends Auth_Base { } } - private function check_app_password($login, $password, $service) { + /** + * @param string $login + * @param string $password + * @param string $service + * @return false|int (false if failed, user id otherwise) + * @throws PDOException + * @throws Exception + */ + private function check_app_password(string $login, string $password, string $service) { $sth = $this->pdo->prepare("SELECT p.id, p.pwd_hash, u.id AS uid FROM ttrss_app_passwords p, ttrss_users u WHERE p.owner_uid = u.id AND LOWER(u.login) = LOWER(?) AND service = ?"); diff --git a/plugins/auth_remote/init.php b/plugins/auth_remote/init.php index 35ee9e31d..9c15d3368 100644 --- a/plugins/auth_remote/init.php +++ b/plugins/auth_remote/init.php @@ -12,7 +12,7 @@ class Auth_Remote extends Auth_Base { $host->add_hook($host::HOOK_AUTH_USER, $this); } - function get_login_by_ssl_certificate() { + function get_login_by_ssl_certificate() : string { $cert_serial = Pref_Prefs::_get_ssl_certificate_id(); if ($cert_serial) { -- cgit v1.2.3-54-g00ecf From 5f808051b2bdb2e43f16693ba19b20940944d556 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 21:14:21 +0300 Subject: deal with phpstan warnings in auto_assign_labels and bookmarklets --- plugins/auto_assign_labels/init.php | 7 ++++++- plugins/bookmarklets/init.php | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/auto_assign_labels/init.php b/plugins/auto_assign_labels/init.php index 84fce8d64..b2e5718ea 100755 --- a/plugins/auto_assign_labels/init.php +++ b/plugins/auto_assign_labels/init.php @@ -11,7 +11,12 @@ class Auto_Assign_Labels extends Plugin { $host->add_hook($host::HOOK_ARTICLE_FILTER, $this); } - function get_all_labels_filter_format($owner_uid) { + /** + * @param int $owner_uid + * @return array> + * @throws PDOException + */ + private function get_all_labels_filter_format(int $owner_uid) : array { $rv = array(); // TODO: use Labels::get_all() diff --git a/plugins/bookmarklets/init.php b/plugins/bookmarklets/init.php index 4bd527623..72aeb2c38 100644 --- a/plugins/bookmarklets/init.php +++ b/plugins/bookmarklets/init.php @@ -1,5 +1,7 @@ Date: Sun, 14 Nov 2021 21:20:59 +0300 Subject: deal with phpstan warnings in plugins/note, nsfw, and share --- plugins/note/init.php | 4 ++-- plugins/nsfw/init.php | 11 +++++++++-- plugins/share/init.php | 5 +---- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'plugins') diff --git a/plugins/note/init.php b/plugins/note/init.php index bc3df64b1..28d3c8c3a 100644 --- a/plugins/note/init.php +++ b/plugins/note/init.php @@ -21,7 +21,7 @@ class Note extends Plugin { style='cursor : pointer' title='".__('Edit article note')."'>note"; } - function edit() { + function edit() : void { $id = clean($_REQUEST['id']); $sth = $this->pdo->prepare("SELECT note FROM ttrss_user_entries WHERE @@ -49,7 +49,7 @@ class Note extends Plugin { $article + * @return array + * @throws PDOException + */ + private function rewrite_contents(array $article) : array { $tags = explode(",", $this->host->get($this, "tags")); $article_tags = $article["tags"]; @@ -101,7 +108,7 @@ class NSFW extends Plugin { "> - - - - + -- cgit v1.2.3-54-g00ecf From c3fbf56984477393669727a296ec229c8d303fbf Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 21:25:56 +0300 Subject: deal with most of warnings in plugins/af_readability --- plugins/af_readability/init.php | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'plugins') diff --git a/plugins/af_readability/init.php b/plugins/af_readability/init.php index 8e75d0c2e..a13f2a5b2 100755 --- a/plugins/af_readability/init.php +++ b/plugins/af_readability/init.php @@ -190,7 +190,11 @@ class Af_Readability extends Plugin { return $article; } - public function extract_content($url) { + /** + * @param string $url + * @return string|false + */ + public function extract_content(string $url) { $tmp = UrlHelper::fetch([ "url" => $url, @@ -224,13 +228,13 @@ class Af_Readability extends Plugin { foreach ($entries as $entry) { if ($entry->hasAttribute("href")) { $entry->setAttribute("href", - rewrite_relative_url(UrlHelper::$fetch_effective_url, $entry->getAttribute("href"))); + UrlHelper::rewrite_relative(UrlHelper::$fetch_effective_url, $entry->getAttribute("href"))); } if ($entry->hasAttribute("src")) { $entry->setAttribute("src", - rewrite_relative_url(UrlHelper::$fetch_effective_url, $entry->getAttribute("src"))); + UrlHelper::rewrite_relative(UrlHelper::$fetch_effective_url, $entry->getAttribute("src"))); } } @@ -246,7 +250,13 @@ class Af_Readability extends Plugin { return false; } - function process_article($article, $append_mode) { + /** + * @param array $article + * @param bool $append_mode + * @return array + * @throws PDOException + */ + function process_article(array $article, bool $append_mode) : array { $extracted_content = $this->extract_content($article["link"]); @@ -263,12 +273,14 @@ class Af_Readability extends Plugin { return $article; } - private function get_stored_array($name) { - $tmp = $this->host->get($this, $name); - - if (!is_array($tmp)) $tmp = []; - - return $tmp; + /** + * @param string $name + * @return array + * @throws PDOException + * @deprecated + */ + private function get_stored_array(string $name) : array { + return $this->host->get_array($this, $name); } function hook_article_filter($article) { @@ -306,7 +318,12 @@ class Af_Readability extends Plugin { return 2; } - private function filter_unknown_feeds($enabled_feeds) { + /** + * @param array $enabled_feeds + * @return array + * @throws PDOException + */ + private function filter_unknown_feeds(array $enabled_feeds) : array { $tmp = array(); foreach ($enabled_feeds as $feed) { @@ -322,7 +339,7 @@ class Af_Readability extends Plugin { return $tmp; } - function embed() { + function embed() : void { $article_id = (int) $_REQUEST["id"]; $sth = $this->pdo->prepare("SELECT link FROM ttrss_entries WHERE id = ?"); -- cgit v1.2.3-54-g00ecf From aa924d9ee7674cfe649d498ce3cbcdb093bca956 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Nov 2021 08:26:02 +0300 Subject: deal with several DOMElement-related errors --- classes/article.php | 1 + classes/feedparser.php | 8 +++++--- plugins/af_comics/filters/af_comics_comicpress.php | 2 +- plugins/af_comics/filters/af_comics_dilbert.php | 2 +- plugins/af_comics/filters/af_comics_gocomics.php | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/classes/article.php b/classes/article.php index 4e25498bc..baeea059b 100755 --- a/classes/article.php +++ b/classes/article.php @@ -602,6 +602,7 @@ class Article extends Handler_Protected { } else if ($e->nodeName == "video") { $article_image = $e->getAttribute("poster"); + /** @var DOMElement|false $src */ $src = $tmpxpath->query("//source[@src]", $e)->item(0); if ($src) { diff --git a/classes/feedparser.php b/classes/feedparser.php index abf1545f8..dd58df941 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -65,10 +65,12 @@ class FeedParser { $this->xpath = $xpath; - $root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)"); + $root_list = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)"); - if (!empty($root) && $root->length > 0) { - $root = $root->item(0); + if (!empty($root_list) && $root_list->length > 0) { + + /** @var DOMElement|false $root */ + $root = $root_list->item(0); if ($root) { switch (mb_strtolower($root->tagName)) { diff --git a/plugins/af_comics/filters/af_comics_comicpress.php b/plugins/af_comics/filters/af_comics_comicpress.php index 741d59672..93bfde7e7 100755 --- a/plugins/af_comics/filters/af_comics_comicpress.php +++ b/plugins/af_comics/filters/af_comics_comicpress.php @@ -32,7 +32,7 @@ class Af_Comics_ComicPress extends Af_ComicFilter { return true; } - // buni-specific + /** @var DOMElement|false $webtoon_link (buni specific) */ $webtoon_link = $xpath->query("//a[contains(@href,'www.webtoons.com')]")->item(0); if ($webtoon_link) { diff --git a/plugins/af_comics/filters/af_comics_dilbert.php b/plugins/af_comics/filters/af_comics_dilbert.php index 49fa54cfa..80a8a0221 100644 --- a/plugins/af_comics/filters/af_comics_dilbert.php +++ b/plugins/af_comics/filters/af_comics_dilbert.php @@ -22,7 +22,7 @@ class Af_Comics_Dilbert extends Af_ComicFilter { if ($res && $doc->loadHTML($res)) { $xpath = new DOMXPath($doc); - // Get the image container + /** @var DOMElement|false $basenode (image container) */ $basenode = $xpath->query('(//div[@class="img-comic-container"]/a[@class="img-comic-link"])')->item(0); // Get the comic title diff --git a/plugins/af_comics/filters/af_comics_gocomics.php b/plugins/af_comics/filters/af_comics_gocomics.php index 71d387918..f474312ae 100644 --- a/plugins/af_comics/filters/af_comics_gocomics.php +++ b/plugins/af_comics/filters/af_comics_gocomics.php @@ -50,6 +50,7 @@ class Af_Comics_Gocomics extends Af_ComicFilter { if (@$doc->loadHTML($body)) { $xpath = new DOMXPath($doc); + /** @var DOMElement|false $node */ $node = $xpath->query('//picture[contains(@class, "item-comic-image")]/img')->item(0); if ($node) { -- cgit v1.2.3-54-g00ecf From 85b974af323a5819c888439bad2bf46ccaaaa4cd Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Nov 2021 13:16:49 +0300 Subject: auth_internal: limit password throttling to failed login attempts not using OTP --- plugins/auth_internal/init.php | 81 ++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 46 deletions(-) (limited to 'plugins') diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php index 1bf3d6a24..688a0f5d8 100644 --- a/plugins/auth_internal/init.php +++ b/plugins/auth_internal/init.php @@ -30,22 +30,6 @@ class Auth_Internal extends Auth_Base { } if ($otp) { - - /*$base32 = new \OTPHP\Base32(); - - $secret = $base32->encode(mb_substr(sha1($row["salt"]), 0, 12), false); - $secret_legacy = $base32->encode(sha1($row["salt"])); - - $totp = new \OTPHP\TOTP($secret); - $otp_check = $totp->now(); - - $totp_legacy = new \OTPHP\TOTP($secret_legacy); - $otp_check_legacy = $totp_legacy->now(); - - if ($otp !== $otp_check && $otp !== $otp_check_legacy) { - return false; - } */ - if ($this->check_password($user_id, $password) && UserHelper::check_otp($user_id, $otp)) return $user_id; else @@ -130,10 +114,42 @@ class Auth_Internal extends Auth_Base { } if ($login) { - $try_user_id = UserHelper::find_user_by_login($login); + $user = ORM::for_table('ttrss_users') + ->where('login', $login) + ->find_one(); + + if ($user) { + if (get_schema_version() >= 145) { + if ($user->last_auth_attempt) { + $last_auth_attempt = strtotime($user->last_auth_attempt); + + if ($last_auth_attempt && time() - $last_auth_attempt < Config::get(Config::AUTH_MIN_INTERVAL)) { + Logger::log(E_USER_NOTICE, "Too many authentication attempts for {$user->login}, throttled."); - if ($try_user_id) { - return $this->check_password($try_user_id, $password); + // start an empty session to deliver login error message + if (session_status() != PHP_SESSION_ACTIVE) + session_start(); + + $_SESSION["login_error_msg"] = __("Too many authentication attempts, throttled."); + + $user->last_auth_attempt = Db::NOW(); + $user->save(); + + return false; + } + } + } + + $auth_result = $this->check_password($user->id, $password); + + if ($auth_result) { + return $auth_result; + } else { + if (get_schema_version() >= 145) { + $user->last_auth_attempt = Db::NOW(); + $user->save(); + } + } } } @@ -153,33 +169,6 @@ class Auth_Internal extends Auth_Base { $user = ORM::for_table('ttrss_users')->find_one($owner_uid); if ($user) { - - // don't throttle app passwords - if (!$service && get_schema_version() >= 145) { - - if ($user->last_auth_attempt) { - $last_auth_attempt = strtotime($user->last_auth_attempt); - - if ($last_auth_attempt && time() - $last_auth_attempt < Config::get(Config::AUTH_MIN_INTERVAL)) { - Logger::log(E_USER_NOTICE, "Too many authentication attempts for {$user->login}, throttled."); - - // start an empty session to deliver login error message - if (session_status() != PHP_SESSION_ACTIVE) - session_start(); - - $_SESSION["login_error_msg"] = __("Too many authentication attempts, throttled."); - - $user->last_auth_attempt = Db::NOW(); - $user->save(); - - return false; - } - } - - $user->last_auth_attempt = Db::NOW(); - $user->save(); - } - $salt = $user['salt'] ?? ""; $login = $user['login']; $pwd_hash = $user['pwd_hash']; -- cgit v1.2.3-54-g00ecf From 109b702ed0cd31a0dc8466b8127882d263705d8d Mon Sep 17 00:00:00 2001 From: wn_ Date: Mon, 15 Nov 2021 12:24:38 +0000 Subject: Minor fix to DOMNodeList#item() potential type (null vs false) --- classes/article.php | 2 +- classes/feedparser.php | 2 +- plugins/af_comics/filters/af_comics_comicpress.php | 2 +- plugins/af_comics/filters/af_comics_dilbert.php | 2 +- plugins/af_comics/filters/af_comics_gocomics.php | 2 +- plugins/af_redditimgur/init.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/classes/article.php b/classes/article.php index baeea059b..1f97f0e16 100755 --- a/classes/article.php +++ b/classes/article.php @@ -602,7 +602,7 @@ class Article extends Handler_Protected { } else if ($e->nodeName == "video") { $article_image = $e->getAttribute("poster"); - /** @var DOMElement|false $src */ + /** @var DOMElement|null $src */ $src = $tmpxpath->query("//source[@src]", $e)->item(0); if ($src) { diff --git a/classes/feedparser.php b/classes/feedparser.php index dd58df941..f5649d2f8 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -69,7 +69,7 @@ class FeedParser { if (!empty($root_list) && $root_list->length > 0) { - /** @var DOMElement|false $root */ + /** @var DOMElement|null $root */ $root = $root_list->item(0); if ($root) { diff --git a/plugins/af_comics/filters/af_comics_comicpress.php b/plugins/af_comics/filters/af_comics_comicpress.php index 93bfde7e7..89837d074 100755 --- a/plugins/af_comics/filters/af_comics_comicpress.php +++ b/plugins/af_comics/filters/af_comics_comicpress.php @@ -32,7 +32,7 @@ class Af_Comics_ComicPress extends Af_ComicFilter { return true; } - /** @var DOMElement|false $webtoon_link (buni specific) */ + /** @var DOMElement|null $webtoon_link (buni specific) */ $webtoon_link = $xpath->query("//a[contains(@href,'www.webtoons.com')]")->item(0); if ($webtoon_link) { diff --git a/plugins/af_comics/filters/af_comics_dilbert.php b/plugins/af_comics/filters/af_comics_dilbert.php index 80a8a0221..a1c59b94c 100644 --- a/plugins/af_comics/filters/af_comics_dilbert.php +++ b/plugins/af_comics/filters/af_comics_dilbert.php @@ -22,7 +22,7 @@ class Af_Comics_Dilbert extends Af_ComicFilter { if ($res && $doc->loadHTML($res)) { $xpath = new DOMXPath($doc); - /** @var DOMElement|false $basenode (image container) */ + /** @var DOMElement|null $basenode (image container) */ $basenode = $xpath->query('(//div[@class="img-comic-container"]/a[@class="img-comic-link"])')->item(0); // Get the comic title diff --git a/plugins/af_comics/filters/af_comics_gocomics.php b/plugins/af_comics/filters/af_comics_gocomics.php index f474312ae..732f7d0b8 100644 --- a/plugins/af_comics/filters/af_comics_gocomics.php +++ b/plugins/af_comics/filters/af_comics_gocomics.php @@ -50,7 +50,7 @@ class Af_Comics_Gocomics extends Af_ComicFilter { if (@$doc->loadHTML($body)) { $xpath = new DOMXPath($doc); - /** @var DOMElement|false $node */ + /** @var DOMElement|null $node */ $node = $xpath->query('//picture[contains(@class, "item-comic-image")]/img')->item(0); if ($node) { diff --git a/plugins/af_redditimgur/init.php b/plugins/af_redditimgur/init.php index aeb75df3a..f40d21d35 100755 --- a/plugins/af_redditimgur/init.php +++ b/plugins/af_redditimgur/init.php @@ -287,7 +287,7 @@ class Af_RedditImgur extends Plugin { $this->generated_enclosures = []; - /** @var DOMElement|false $anchor -- embed anchor element, before reddit
post layout */ + /** @var DOMElement|null $anchor -- embed anchor element, before reddit
post layout */ $anchor = $xpath->query('//body/*')->item(0); // deal with json-provided media content first -- cgit v1.2.3-54-g00ecf From b2952843f50c7b5d2e8aafd62fadb4674acc59b1 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Nov 2021 23:22:21 +0300 Subject: * DiskCache: add download() helper * Af_Comics_Gocomics_FarSide: cache linked images because it seems to be required anyway --- classes/diskcache.php | 20 ++++++++++++++++++++ .../af_comics/filters/af_comics_gocomics_farside.php | 16 +++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/classes/diskcache.php b/classes/diskcache.php index ed334b2d2..0df8d7cd4 100644 --- a/classes/diskcache.php +++ b/classes/diskcache.php @@ -253,6 +253,26 @@ class DiskCache { return touch($this->get_full_path($filename)); } + /** Downloads $url to cache as $local_filename if its missing (unless $force-ed) + * @param string $url + * @param string $local_filename + * @param array $options (additional params to UrlHelper::fetch()) + * @param bool $force + * @return bool + */ + public function download(string $url, string $local_filename, array $options = [], bool $force = false) : bool { + if ($this->exists($local_filename) && !$force) + return true; + + $data = UrlHelper::fetch(array_merge(["url" => $url, + "max_size" => Config::get(Config::MAX_CACHE_FILE_SIZE)], $options)); + + if ($data) + return $this->put($local_filename, $data) > 0; + + return false; + } + public function get(string $filename): ?string { if ($this->exists($filename)) return file_get_contents($this->get_full_path($filename)); diff --git a/plugins/af_comics/filters/af_comics_gocomics_farside.php b/plugins/af_comics/filters/af_comics_gocomics_farside.php index 0399015ab..e4e230516 100644 --- a/plugins/af_comics/filters/af_comics_gocomics_farside.php +++ b/plugins/af_comics/filters/af_comics_gocomics_farside.php @@ -50,8 +50,22 @@ class Af_Comics_Gocomics_FarSide extends Af_ComicFilter { if ($content_node) { $imgs = $xpath->query('//img[@data-src]', $content_node); + $cache = new DiskCache("images"); + foreach ($imgs as $img) { - $img->setAttribute('src', $img->getAttribute('data-src')); + $image_url = $img->getAttribute('data-src'); + $local_filename = sha1($image_url); + + if ($image_url) { + $img->setAttribute('src', $image_url); + + // try to cache image locally because they just 401 us otherwise + if (!$cache->exists($local_filename)) { + Debug::log("[Af_Comics_Gocomics_FarSide] caching: $image_url", Debug::LOG_VERBOSE); + $res = $cache->download($image_url, sha1($image_url), ["http_referrer" => $image_url]); + Debug::log("[Af_Comics_Gocomics_FarSide] cache result: $res", Debug::LOG_VERBOSE); + } + } } $junk_elems = $xpath->query("//*[@data-shareable-popover]"); -- cgit v1.2.3-54-g00ecf