summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/af_comics/filter_base.php18
-rwxr-xr-xplugins/af_comics/filters/af_comics_comicpress.php2
-rw-r--r--plugins/af_comics/filters/af_comics_dilbert.php2
-rw-r--r--plugins/af_comics/filters/af_comics_gocomics.php1
-rw-r--r--plugins/af_comics/filters/af_comics_gocomics_farside.php16
-rw-r--r--plugins/af_comics/filters/af_comics_tfd.php2
-rwxr-xr-xplugins/af_comics/init.php1
-rw-r--r--plugins/af_psql_trgm/init.php41
-rwxr-xr-xplugins/af_readability/init.php45
-rwxr-xr-xplugins/af_redditimgur/init.php80
-rw-r--r--plugins/af_youtube_embed/init.php4
-rw-r--r--plugins/auth_internal/init.php98
-rw-r--r--plugins/auth_remote/init.php4
-rwxr-xr-xplugins/auto_assign_labels/init.php7
-rw-r--r--plugins/bookmarklets/init.php7
-rwxr-xr-xplugins/cache_starred_images/init.php33
-rw-r--r--plugins/no_iframes/init.php2
-rw-r--r--plugins/note/init.php4
-rw-r--r--plugins/nsfw/init.php11
-rw-r--r--plugins/share/init.php24
20 files changed, 263 insertions, 139 deletions
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 @@
<?php
abstract class Af_ComicFilter {
+ /** @return array<string> */
public abstract function supported();
+
+ /**
+ * @param array<string,mixed> $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_comicpress.php b/plugins/af_comics/filters/af_comics_comicpress.php
index 741d59672..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;
}
- // 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 49fa54cfa..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);
- // Get the 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 71d387918..732f7d0b8 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|null $node */
$node = $xpath->query('//picture[contains(@class, "item-comic-image")]/img')->item(0);
if ($node) {
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]");
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();
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 @@
<?php
class Af_Comics extends Plugin {
+ /** @var array<object> $filters */
private $filters = array();
function about() {
diff --git a/plugins/af_psql_trgm/init.php b/plugins/af_psql_trgm/init.php
index 87415450b..89b66e20b 100644
--- a/plugins/af_psql_trgm/init.php
+++ b/plugins/af_psql_trgm/init.php
@@ -1,9 +1,13 @@
<?php
class Af_Psql_Trgm extends Plugin {
- /* @var PluginHost $host */
+ /** @var PluginHost $host */
private $host;
+
+ /** @var float */
private $default_similarity = 0.75;
+
+ /** @var int */
private $default_min_length = 32;
function about() {
@@ -12,6 +16,7 @@ class Af_Psql_Trgm extends Plugin {
"fox");
}
+ /** @return void */
function save() {
$similarity = (float) $_POST["similarity"];
$min_title_length = (int) $_POST["min_title_length"];
@@ -45,6 +50,7 @@ class Af_Psql_Trgm extends Plugin {
return file_get_contents(__DIR__ . "/init.js");
}
+ /** @return void */
function showrelated() {
$id = (int) $_REQUEST['id'];
$owner_uid = $_SESSION["uid"];
@@ -196,7 +202,7 @@ class Af_Psql_Trgm extends Plugin {
<?php
/* cleanup */
$enabled_feeds = $this->filter_unknown_feeds(
- $this->get_stored_array("enabled_feeds"));
+ $this->host->get_array($this, "enabled_feeds"));
$this->host->set($this, "enabled_feeds", $enabled_feeds);
?>
@@ -221,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");
?>
<header><?= __("Similarity (af_psql_trgm)") ?></header>
@@ -238,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);
@@ -267,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;
}
@@ -275,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;
}
@@ -321,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;
}
@@ -336,7 +342,12 @@ class Af_Psql_Trgm extends Plugin {
return 2;
}
- private function filter_unknown_feeds($enabled_feeds) {
+ /**
+ * @param array<int> $enabled_feeds
+ * @return array<int>
+ * @throws PDOException
+ */
+ private function filter_unknown_feeds($enabled_feeds) : array {
$tmp = array();
foreach ($enabled_feeds as $feed) {
@@ -351,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;
- }
-
-
}
diff --git a/plugins/af_readability/init.php b/plugins/af_readability/init.php
index a39cc278e..a13f2a5b2 100755
--- a/plugins/af_readability/init.php
+++ b/plugins/af_readability/init.php
@@ -6,7 +6,7 @@ use \andreskrey\Readability\Configuration;
class Af_Readability extends Plugin {
- /* @var PluginHost $host */
+ /** @var PluginHost $host */
private $host;
function about() {
@@ -19,6 +19,7 @@ class Af_Readability extends Plugin {
return array("needs_curl" => true);
}
+ /** @return void */
function save() {
$enable_share_anything = checkbox_to_sql_bool($_POST["enable_share_anything"] ?? "");
@@ -186,9 +187,14 @@ class Af_Readability extends Plugin {
case "action_append":
return $this->process_article($article, true);
}
+ return $article;
}
- public function extract_content($url) {
+ /**
+ * @param string $url
+ * @return string|false
+ */
+ public function extract_content(string $url) {
$tmp = UrlHelper::fetch([
"url" => $url,
@@ -222,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")));
}
}
@@ -244,7 +250,13 @@ class Af_Readability extends Plugin {
return false;
}
- function process_article($article, $append_mode) {
+ /**
+ * @param array<string, mixed> $article
+ * @param bool $append_mode
+ * @return array<string,mixed>
+ * @throws PDOException
+ */
+ function process_article(array $article, bool $append_mode) : array {
$extracted_content = $this->extract_content($article["link"]);
@@ -261,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<int|string, mixed>
+ * @throws PDOException
+ * @deprecated
+ */
+ private function get_stored_array(string $name) : array {
+ return $this->host->get_array($this, $name);
}
function hook_article_filter($article) {
@@ -304,7 +318,12 @@ class Af_Readability extends Plugin {
return 2;
}
- private function filter_unknown_feeds($enabled_feeds) {
+ /**
+ * @param array<int> $enabled_feeds
+ * @return array<int>
+ * @throws PDOException
+ */
+ private function filter_unknown_feeds(array $enabled_feeds) : array {
$tmp = array();
foreach ($enabled_feeds as $feed) {
@@ -320,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 = ?");
diff --git a/plugins/af_redditimgur/init.php b/plugins/af_redditimgur/init.php
index bd4032050..f40d21d35 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<string> */
private $domain_blacklist = [ "github.com" ];
+
+ /** @var bool */
private $dump_json_data = false;
+
+ /** @var array<string> */
private $fallback_preview_urls = [];
+
+ /** @var int */
private $default_max_score = 100;
+
+ /** @var array<int, array<int, string|null>> */
private $generated_enclosures = [];
function about() {
@@ -118,7 +128,7 @@ class Af_RedditImgur extends Plugin {
<?php
}
- function save() {
+ function save() : void {
$enable_readability = checkbox_to_sql_bool($_POST["enable_readability"] ?? "");
$enable_content_dupcheck = checkbox_to_sql_bool($_POST["enable_content_dupcheck"] ?? "");
$reddit_to_teddit = checkbox_to_sql_bool($_POST["reddit_to_teddit"] ?? "");
@@ -138,7 +148,14 @@ class Af_RedditImgur extends Plugin {
echo __("Configuration saved");
}
- private function process_post_media($data, $doc, $xpath, $anchor) {
+ /**
+ * @param array<string,mixed> $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<string, mixed> $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 <table> post layout
+ /** @var DOMElement|null $anchor -- embed anchor element, before reddit <table> 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<string,mixed> $article
+ * @param string $url
+ * @param DOMDocument $doc
+ * @param DOMXPath $xpath
+ * @param bool $debug
+ * @return array<string,mixed>
+ * @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<string> $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;
diff --git a/plugins/af_youtube_embed/init.php b/plugins/af_youtube_embed/init.php
index 771ee8c46..ff44bb291 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"];
@@ -32,6 +32,8 @@ class Af_Youtube_Embed extends Plugin {
</div>";
}
+
+ return "";
}
function api_version() {
diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php
index 77f7596f0..688a0f5d8 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);
@@ -29,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
@@ -129,48 +114,61 @@ class Auth_Internal extends Auth_Base {
}
if ($login) {
- $try_user_id = $this->find_user_by_login($login);
-
- if ($try_user_id) {
- return $this->check_password($try_user_id, $password);
- }
- }
-
- return false;
- }
-
- function check_password(int $owner_uid, string $password, string $service = '') {
+ $user = ORM::for_table('ttrss_users')
+ ->where('login', $login)
+ ->find_one();
- $user = ORM::for_table('ttrss_users')->find_one($owner_uid);
+ if ($user) {
+ if (get_schema_version() >= 145) {
+ if ($user->last_auth_attempt) {
+ $last_auth_attempt = strtotime($user->last_auth_attempt);
- if ($user) {
+ 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.");
- // don't throttle app passwords
- if (!$service && get_schema_version() >= 145) {
+ // start an empty session to deliver login error message
+ if (session_status() != PHP_SESSION_ACTIVE)
+ session_start();
- if ($user->last_auth_attempt) {
- $last_auth_attempt = strtotime($user->last_auth_attempt);
+ $_SESSION["login_error_msg"] = __("Too many authentication attempts, throttled.");
- 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.");
+ $user->last_auth_attempt = Db::NOW();
+ $user->save();
- // start an empty session to deliver login error message
- if (session_status() != PHP_SESSION_ACTIVE)
- session_start();
+ return false;
+ }
+ }
+ }
- $_SESSION["login_error_msg"] = __("Too many authentication attempts, throttled.");
+ $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();
-
- return false;
}
}
-
- $user->last_auth_attempt = Db::NOW();
- $user->save();
}
+ }
+ 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);
+
+ if ($user) {
$salt = $user['salt'] ?? "";
$login = $user['login'];
$pwd_hash = $user['pwd_hash'];
@@ -202,7 +200,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)) {
@@ -245,7 +243,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 b240a9402..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) {
@@ -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/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<int, array<int, int|string>>
+ * @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 @@
<?php
class Bookmarklets extends Plugin {
+
+ /** @var PluginHost $host */
private $host;
function about() {
@@ -20,7 +22,7 @@ class Bookmarklets extends Plugin {
return in_array($method, ["subscribe", "sharepopup"]);
}
- function subscribe() {
+ function subscribe() : void {
if (Config::get(Config::SINGLE_USER_MODE)) {
UserHelper::login_sequence();
}
@@ -171,7 +173,7 @@ class Bookmarklets extends Plugin {
}
}
- function sharepopup() {
+ function sharepopup() : void {
if (Config::get(Config::SINGLE_USER_MODE)) {
UserHelper::login_sequence();
}
@@ -332,7 +334,6 @@ class Bookmarklets extends Plugin {
<?php
}
-
function hook_prefs_tab($args) {
if ($args != "prefFeeds")
return;
diff --git a/plugins/cache_starred_images/init.php b/plugins/cache_starred_images/init.php
index d94e60504..731007b5b 100755
--- a/plugins/cache_starred_images/init.php
+++ b/plugins/cache_starred_images/init.php
@@ -1,11 +1,14 @@
<?php
class Cache_Starred_Images extends Plugin {
- /* @var PluginHost $host */
+ /** @var PluginHost $host */
private $host;
- /* @var DiskCache $cache */
+
+ /** @var DiskCache $cache */
private $cache;
- private $max_cache_attempts = 5; // per-article
+
+ /** @var int $max_cache_attempts (per article) */
+ private $max_cache_attempts = 5;
function about() {
return array(null,
@@ -32,8 +35,8 @@ class Cache_Starred_Images extends Plugin {
}
}
+ /** since HOOK_UPDATE_TASK is not available to user plugins, this hook is a next best thing */
function hook_house_keeping() {
- /* since HOOK_UPDATE_TASK is not available to user plugins, this hook is a next best thing */
Debug::log("caching media of starred articles for user " . $this->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"]);
@@ -97,7 +100,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)) {
@@ -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;
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');
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</i>";
}
- 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 {
<?php
}
- function setNote() {
+ function setNote() : void {
$id = (int)clean($_REQUEST["id"]);
$note = clean($_REQUEST["note"]);
diff --git a/plugins/nsfw/init.php b/plugins/nsfw/init.php
index fc38fef71..a349ceac0 100644
--- a/plugins/nsfw/init.php
+++ b/plugins/nsfw/init.php
@@ -1,5 +1,7 @@
<?php
class NSFW extends Plugin {
+
+ /** @var PluginHost $host */
private $host;
function about() {
@@ -31,7 +33,12 @@ class NSFW extends Plugin {
}
}
- private function rewrite_contents($article) {
+ /**
+ * @param array<string, mixed> $article
+ * @return array<string,mixed>
+ * @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 {
<?php
}
- function save() {
+ function save() : void {
$tags = implode(", ",
FeedItem_Common::normalize_categories(explode(",", $_POST["tags"] ?? "")));
diff --git a/plugins/share/init.php b/plugins/share/init.php
index 359d86802..0b14c673b 100644
--- a/plugins/share/init.php
+++ b/plugins/share/init.php
@@ -1,5 +1,6 @@
<?php
class Share extends Plugin {
+ /** @var PluginHost $host */
private $host;
function about() {
@@ -8,7 +9,6 @@ class Share extends Plugin {
"fox");
}
- /* @var PluginHost $host */
function init($host) {
$this->host = $host;
@@ -32,6 +32,7 @@ class Share extends Plugin {
return file_get_contents(__DIR__ . "/share_prefs.js");
}
+ /** @return void */
function unshare() {
$id = $_REQUEST['id'];
@@ -42,6 +43,9 @@ class Share extends Plugin {
print __("Article unshared");
}
+ /**
+ * @param string $id
+ * @return void */
function hook_prefs_tab_section($id) {
if ($id == "prefFeedsPublishedGenerated") {
?>
@@ -56,6 +60,7 @@ class Share extends Plugin {
}
}
+ /** @return void */
function clearArticleKeys() {
$sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET uuid = '' WHERE
owner_uid = ?");
@@ -64,6 +69,7 @@ class Share extends Plugin {
print __("Shared URLs cleared.");
}
+ /** @return void */
function newkey() {
$id = $_REQUEST['id'];
$uuid = uniqid_short();
@@ -75,6 +81,10 @@ class Share extends Plugin {
print json_encode(["link" => $uuid]);
}
+ /**
+ * @param array<string,mixed> $line
+ *
+ * @return string */
function hook_article_button($line) {
$icon_class = !empty($line['uuid']) ? "is-shared" : "";
@@ -83,6 +93,7 @@ class Share extends Plugin {
title='".__('Share by URL')."'>link</i>";
}
+ /** @return void */
function get() {
$uuid = clean($_REQUEST["key"] ?? "");
@@ -107,7 +118,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();
@@ -133,7 +144,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) {
@@ -183,10 +194,7 @@ class Share extends Plugin {
strip_tags($content_decoded)
)
), 500, "...")) ?>">
-
- <?php if ($og_image) { ?>
- <meta property='og:image' content="<?= htmlspecialchars($og_image) ?>">
- <?php } ?>
+ <meta property='og:image' content="<?= htmlspecialchars($og_image) ?>">
</head>
<body class='flat ttrss_utility ttrss_zoom css_loading'>
@@ -231,6 +239,7 @@ class Share extends Plugin {
}
}
+ /** @return void */
function shareDialog() {
$id = (int)clean($_REQUEST['id'] ?? 0);
@@ -276,6 +285,7 @@ class Share extends Plugin {
<?php
}
+ /** @return int */
function api_version() {
return 2;
}