diff options
Diffstat (limited to 'classes')
-rwxr-xr-x | classes/api.php | 19 | ||||
-rwxr-xr-x | classes/article.php | 12 | ||||
-rw-r--r-- | classes/backend.php | 2 | ||||
-rw-r--r-- | classes/counters.php | 3 | ||||
-rw-r--r-- | classes/db/prefs.php | 12 | ||||
-rw-r--r-- | classes/dbupdater.php | 4 | ||||
-rw-r--r-- | classes/digest.php | 6 | ||||
-rw-r--r-- | classes/diskcache.php | 8 | ||||
-rw-r--r-- | classes/dlg.php | 2 | ||||
-rw-r--r-- | classes/feedparser.php | 4 | ||||
-rwxr-xr-x | classes/feeds.php | 58 | ||||
-rwxr-xr-x | classes/handler/public.php | 12 | ||||
-rw-r--r-- | classes/labels.php | 2 | ||||
-rwxr-xr-x | classes/logger/sql.php | 2 | ||||
-rw-r--r-- | classes/opml.php | 11 | ||||
-rwxr-xr-x | classes/pluginhost.php | 20 | ||||
-rwxr-xr-x | classes/pref/feeds.php | 50 | ||||
-rwxr-xr-x | classes/pref/filters.php | 12 | ||||
-rw-r--r-- | classes/pref/labels.php | 2 | ||||
-rw-r--r-- | classes/pref/prefs.php | 12 | ||||
-rw-r--r-- | classes/pref/system.php | 174 | ||||
-rw-r--r-- | classes/pref/users.php | 23 | ||||
-rwxr-xr-x | classes/rpc.php | 22 | ||||
-rwxr-xr-x | classes/rssutils.php | 27 | ||||
-rw-r--r-- | classes/sanitizer.php | 16 | ||||
-rw-r--r-- | classes/timehelper.php | 5 | ||||
-rw-r--r-- | classes/urlhelper.php | 63 | ||||
-rw-r--r-- | classes/userhelper.php | 6 |
28 files changed, 309 insertions, 280 deletions
diff --git a/classes/api.php b/classes/api.php index aa39171bf..7125e52aa 100755 --- a/classes/api.php +++ b/classes/api.php @@ -174,7 +174,7 @@ class API extends Handler { $unread = getFeedUnread($cat_id, true); if ($unread || !$unread_only) { - array_push($cats, array("id" => (int) $cat_id, + array_push($cats, array("id" => $cat_id, "title" => Feeds::getCategoryTitle($cat_id), "unread" => (int) $unread)); } @@ -243,6 +243,7 @@ class API extends Handler { $field = ""; $set_to = ""; + $additional_fields = ""; switch ($field_raw) { case 0: @@ -718,8 +719,8 @@ class API extends Handler { $label_cache = json_decode($label_cache, true); if ($label_cache) { - if ($label_cache["no-labels"] == 1) - $labels = array(); + if (($label_cache["no-labels"] ?? 0) == 1) + $labels = []; else $labels = $label_cache; } @@ -762,7 +763,7 @@ class API extends Handler { } // unify label output to ease parsing - if ($labels["no-labels"] == 1) $labels = array(); + if (($labels["no-labels"] ?? 0) == 1) $labels = []; $headline_row["labels"] = $labels; @@ -842,14 +843,8 @@ class API extends Handler { $_REQUEST['mode'] = 2; $_REQUEST['force_show_empty'] = $include_empty; - if ($pf){ - $data = $pf->makefeedtree(); - $this->wrap(self::STATUS_OK, array("categories" => $data)); - } else { - $this->wrap(self::STATUS_ERR, array("error" => - 'UNABLE_TO_INSTANTIATE_OBJECT')); - } - + $this->wrap(self::STATUS_OK, + array("categories" => $pf->makefeedtree())); } // only works for labels or uncategorized for the time being diff --git a/classes/article.php b/classes/article.php index 3a58f4576..ff7f11180 100755 --- a/classes/article.php +++ b/classes/article.php @@ -197,7 +197,7 @@ class Article extends Handler_Protected { $sth->execute(array_merge([$score], $ids, [$_SESSION['uid']])); - print json_encode(["id" => $ids, "score" => (int)$score]); + print json_encode(["id" => $ids, "score" => $score]); } function getScore() { @@ -267,7 +267,7 @@ class Article extends Handler_Protected { $this->pdo->commit(); $tags = self::get_article_tags($id); - $tags_str = $this->format_tags_string($tags, $id); + $tags_str = $this->format_tags_string($tags); $tags_str_full = join(", ", $tags); if (!$tags_str_full) $tags_str_full = __("no tags"); @@ -419,7 +419,7 @@ class Article extends Handler_Protected { $retval = $plugin->hook_render_enclosure($entry, $hide_images); - if ($retval) { + if (!empty($retval)) { $rv .= $retval; } else { @@ -584,8 +584,6 @@ class Article extends Handler_Protected { <i class='material-icons'>note</i> <div $onclick class='body'>$note</div> </div>"; - - return $str; } static function get_article_enclosures($id) { @@ -687,7 +685,7 @@ class Article extends Handler_Protected { if ($label_cache) { $tmp = json_decode($label_cache, true); - if (!$tmp || $tmp["no-labels"] == 1) + if (empty($tmp) || ($tmp["no-labels"] ?? 0) == 1) return $rv; else return $tmp; @@ -778,7 +776,7 @@ class Article extends Handler_Protected { if ($article_image) { $article_image = rewrite_relative_url($site_url, $article_image); - if (!$article_kind && (count($enclosures) > 1 || $elems->length > 1)) + if (!$article_kind && (count($enclosures) > 1 || (isset($elems) && $elems->length > 1))) $article_kind = ARTICLE_KIND_ALBUM; } diff --git a/classes/backend.php b/classes/backend.php index 16c20660a..6e0fa191e 100644 --- a/classes/backend.php +++ b/classes/backend.php @@ -40,7 +40,7 @@ class Backend extends Handler_Protected { foreach ($hotkeys as $action => $description) { - if (is_array($omap[$action])) { + if (!empty($omap[$action])) { foreach ($omap[$action] as $sequence) { if (strpos($sequence, "|") !== false) { $sequence = substr($sequence, diff --git a/classes/counters.php b/classes/counters.php index be634c52a..59605df18 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -120,7 +120,8 @@ class Counters { $has_img = false; } - if (date('Y') - date('Y', strtotime($line['last_updated'])) > 2) + // hide default un-updated timestamp i.e. 1980-01-01 (?) -fox + if ((int)date('Y') - (int)date('Y', strtotime($line['last_updated'])) > 2) $last_updated = ''; $cv = [ diff --git a/classes/db/prefs.php b/classes/db/prefs.php index fbe7e0eea..24153b19a 100644 --- a/classes/db/prefs.php +++ b/classes/db/prefs.php @@ -8,7 +8,7 @@ class Db_Prefs { $this->pdo = Db::pdo(); $this->cache = array(); - if ($_SESSION["uid"]) $this->cache(); + if (!empty($_SESSION["uid"])) $this->cache(); } private function __clone() { @@ -24,7 +24,7 @@ class Db_Prefs { function cache() { $user_id = $_SESSION["uid"]; - @$profile = $_SESSION["profile"]; + $profile = $_SESSION["profile"] ?? false; if (!is_numeric($profile) || !$profile || get_schema_version() < 63) $profile = null; @@ -55,12 +55,12 @@ class Db_Prefs { if (!$user_id) { $user_id = $_SESSION["uid"]; - @$profile = $_SESSION["profile"]; + $profile = $_SESSION["profile"] ?? false; } else { $profile = false; } - if ($user_id == $_SESSION['uid'] && isset($this->cache[$pref_name])) { + if ($user_id == ($_SESSION['uid'] ?? false) && isset($this->cache[$pref_name])) { $tuple = $this->cache[$pref_name]; return $this->convert($tuple["value"], $tuple["type"]); } @@ -83,7 +83,7 @@ class Db_Prefs { $value = $row["value"]; $type_name = $row["type_name"]; - if ($user_id == $_SESSION["uid"]) { + if ($user_id == ($_SESSION["uid"] ?? false)) { $this->cache[$pref_name]["type"] = $type_name; $this->cache[$pref_name]["value"] = $value; } @@ -113,7 +113,7 @@ class Db_Prefs { if (!$user_id) { $user_id = $_SESSION["uid"]; - @$profile = $_SESSION["profile"]; + @$profile = $_SESSION["profile"] ?? false; } else { $profile = null; } diff --git a/classes/dbupdater.php b/classes/dbupdater.php index 94307aea0..3cc6e9125 100644 --- a/classes/dbupdater.php +++ b/classes/dbupdater.php @@ -6,7 +6,7 @@ class DbUpdater { private $need_version; function __construct($pdo, $db_type, $need_version) { - $this->pdo = Db::pdo(); //$pdo; + $this->pdo = $pdo; $this->db_type = $db_type; $this->need_version = (int) $need_version; } @@ -24,7 +24,7 @@ class DbUpdater { $filename = "schema/versions/".$this->db_type."/$version.sql"; if (file_exists($filename)) { - return explode(";", preg_replace("/[\r\n]/", "", file_get_contents($filename))); + return explode(";", (string)preg_replace("/[\r\n]/", "", (string)file_get_contents($filename))); } else { user_error("DB Updater: schema file for version $version is not found."); return false; diff --git a/classes/digest.php b/classes/digest.php index 5128b4186..7790424ca 100644 --- a/classes/digest.php +++ b/classes/digest.php @@ -5,8 +5,6 @@ class Digest /** * Send by mail a digest of last articles. * - * @param mixed $link The database connection. - * @param integer $limit The maximum number of articles by digest. * @return boolean Return false if digests are not enabled. */ static function send_headlines_digests() { @@ -18,7 +16,7 @@ class Digest if (DB_TYPE == "pgsql") { $interval_qpart = "last_digest_sent < NOW() - INTERVAL '1 days'"; - } else if (DB_TYPE == "mysql") { + } else /* if (DB_TYPE == "mysql") */ { $interval_qpart = "last_digest_sent < DATE_SUB(NOW(), INTERVAL 1 DAY)"; } @@ -113,7 +111,7 @@ class Digest if (DB_TYPE == "pgsql") { $interval_qpart = "ttrss_entries.date_updated > NOW() - INTERVAL '$days days'"; - } else if (DB_TYPE == "mysql") { + } else /* if (DB_TYPE == "mysql") */ { $interval_qpart = "ttrss_entries.date_updated > DATE_SUB(NOW(), INTERVAL $days DAY)"; } diff --git a/classes/diskcache.php b/classes/diskcache.php index daa171bf6..dcd7791d8 100644 --- a/classes/diskcache.php +++ b/classes/diskcache.php @@ -329,7 +329,9 @@ class DiskCache { } if ($need_saving) { - $doc->removeChild($doc->firstChild); //remove doctype + if (isset($doc->firstChild)) + $doc->removeChild($doc->firstChild); //remove doctype + $res = $doc->saveHTML(); } } @@ -384,7 +386,7 @@ class DiskCache { $mimetype_blacklist = [ "image/svg+xml" ]; /* only serve video and images */ - if (!preg_match("/(image|audio|video)\//", $mimetype) || in_array($mimetype, $mimetype_blacklist)) { + if (!preg_match("/(image|audio|video)\//", (string)$mimetype) || in_array($mimetype, $mimetype_blacklist)) { http_response_code(400); header("Content-type: text/plain"); @@ -403,7 +405,7 @@ class DiskCache { header("Content-type: $mimetype"); - $stamp = gmdate("D, d M Y H:i:s", filemtime($filename)) . " GMT"; + $stamp = gmdate("D, d M Y H:i:s", (int)filemtime($filename)) . " GMT"; header("Last-Modified: $stamp", true); return readfile($filename); diff --git a/classes/dlg.php b/classes/dlg.php index 8873a0cb9..2fa232053 100644 --- a/classes/dlg.php +++ b/classes/dlg.php @@ -136,7 +136,7 @@ class Dlg extends Handler_Protected { // and add the $min_size set above $size = round($min_size + (($value - $min_qty) * $step)); - $key_escaped = str_replace("'", "\\'", $key); + $key_escaped = str_replace("'", "\\'", (string)$key); echo "<a href=\"#\" onclick=\"Feeds.open({feed:'$key_escaped'}) \" style=\"font-size: " . $size . "px\" title=\"$value articles tagged with " . diff --git a/classes/feedparser.php b/classes/feedparser.php index 9677164d3..daba271fb 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -53,7 +53,7 @@ class FeedParser { $root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)"); - if ($root && $root->length > 0) { + if (!empty($root) && $root->length > 0) { $root = $root->item(0); if ($root) { @@ -106,7 +106,7 @@ class FeedParser { $articles = $xpath->query("//atom:entry"); - if (!$articles || $articles->length == 0) + if (empty($articles) || $articles->length == 0) $articles = $xpath->query("//atom03:entry"); foreach ($articles as $article) { diff --git a/classes/feeds.php b/classes/feeds.php index 2015f2435..194a41c98 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -20,7 +20,7 @@ class Feeds extends Handler_Protected { $feed_id, $is_cat, $search, $error, $feed_last_updated) { - if ($is_cat) $cat_q = "&is_cat=$is_cat"; + $cat_q = $is_cat ? "&is_cat=$is_cat" : ""; if ($search) { $search_q = "&q=$search"; @@ -31,7 +31,7 @@ class Feeds extends Handler_Protected { $reply = ""; $rss_link = htmlspecialchars(get_self_url_prefix() . - "/public.php?op=rss&id=$feed_id$cat_q$search_q"); + "/public.php?op=rss&id=${feed_id}${cat_q}${search_q}"); $reply .= "<span class='left'>"; @@ -115,10 +115,9 @@ class Feeds extends Handler_Protected { $this->mark_timestamp("init"); - $reply = array(); - - $rgba_cache = array(); - $topmost_article_ids = array(); + $reply = []; + $rgba_cache = []; + $topmost_article_ids = []; if (!$offset) $offset = 0; if ($method == "undefined") $method = ""; @@ -147,13 +146,15 @@ class Feeds extends Handler_Protected { } } - @$search = $_REQUEST["query"]; - @$search_language = $_REQUEST["search_language"]; // PGSQL only + $search = $_REQUEST["query"] ?? ""; + $search_language = $_REQUEST["search_language"] ?? ""; // PGSQL only if ($search) { $disable_cache = true; } + $qfh_ret = []; + if (!$cat_view && is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) { $handler = PluginHost::getInstance()->get_feed_handler( PluginHost::feed_to_pfeed_id($feed)); @@ -220,19 +221,19 @@ class Feeds extends Handler_Protected { $feed, $cat_view, $search, $last_error, $last_updated); + $reply['content'] = []; + if ($offset == 0) { foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINES_BEFORE) as $p) { $reply['content'] .= $p->hook_headlines_before($feed, $cat_view, $qfh_ret); } } - $reply['content'] = []; - $this->mark_timestamp("object header"); $headlines_count = 0; - if (is_object($result)) { + if ($result instanceof PDOStatement) { while ($line = $result->fetch(PDO::FETCH_ASSOC)) { $this->mark_timestamp("article start: " . $line["id"] . " " . $line["title"]); @@ -274,7 +275,7 @@ class Feeds extends Handler_Protected { $label_cache = json_decode($label_cache, true); if ($label_cache) { - if ($label_cache["no-labels"] == 1) + if ($label_cache["no-labels"] ?? false == 1) $labels = array(); else $labels = $label_cache; @@ -295,7 +296,7 @@ class Feeds extends Handler_Protected { $this->mark_timestamp(" labels"); - if (!$line["feed_title"]) $line["feed_title"] = ""; + $line["feed_title"] = $line["feed_title"] ?? ""; $line["buttons_left"] = ""; foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_LEFT_BUTTON) as $p) { @@ -363,7 +364,7 @@ class Feeds extends Handler_Protected { else $tags = false; - $line["tags_str"] = Article::format_tags_string($tags, $id); + $line["tags_str"] = Article::format_tags_string($tags); $this->mark_timestamp(" tags"); @@ -374,7 +375,7 @@ class Feeds extends Handler_Protected { } //setting feed headline background color, needs to change text color based on dark/light - $fav_color = $line['favicon_avg_color']; + $fav_color = $line['favicon_avg_color'] ?? false; $this->mark_timestamp(" pre-color"); @@ -410,7 +411,7 @@ class Feeds extends Handler_Protected { if (!$headlines_count) { - if (is_object($result)) { + if ($result instanceof PDOStatement) { if ($query_error_override) { $message = $query_error_override; @@ -483,14 +484,14 @@ class Feeds extends Handler_Protected { $reply = array(); $feed = $_REQUEST["feed"]; - $method = $_REQUEST["m"]; + $method = $_REQUEST["m"] ?? ""; $view_mode = $_REQUEST["view_mode"]; $limit = 30; - @$cat_view = $_REQUEST["cat"] == "true"; - @$next_unread_feed = $_REQUEST["nuf"]; - @$offset = $_REQUEST["skip"]; + $cat_view = $_REQUEST["cat"] == "true"; + $next_unread_feed = $_REQUEST["nuf"] ?? 0; + $offset = $_REQUEST["skip"] ?? 0; $order_by = $_REQUEST["order_by"]; - $check_first_id = $_REQUEST["fid"]; + $check_first_id = $_REQUEST["fid"] ?? 0; if (is_numeric($feed)) $feed = (int) $feed; @@ -564,7 +565,7 @@ class Feeds extends Handler_Protected { else $reply['headlines']['id'] = $next_unread_feed; - $reply['headlines']['is_cat'] = (bool) $cat_view; + $reply['headlines']['is_cat'] = $cat_view; $reply['headlines-info'] = ["count" => (int) $headlines_count, "disable_cache" => (bool) $disable_cache]; @@ -772,7 +773,7 @@ class Feeds extends Handler_Protected { Debug::set_loglevel($xdebug); $feed_id = (int)$_REQUEST["feed_id"]; - @$do_update = $_REQUEST["action"] == "do_update"; + $do_update = ($_REQUEST["action"] ?? "") == "do_update"; $csrf_token = $_POST["csrf_token"]; $sth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE id = ? AND owner_uid = ?"); @@ -1087,7 +1088,7 @@ class Feeds extends Handler_Protected { } else if ($n_feed >= 0) { if ($n_feed != 0) { - $match_part = "feed_id = " . (int)$n_feed; + $match_part = sprintf("feed_id = %d", $n_feed); } else { $match_part = "feed_id IS NULL"; } @@ -1794,7 +1795,7 @@ class Feeds extends Handler_Protected { $sanity_interval_qpart $first_id_query_strategy_part ORDER BY $order_by LIMIT 1"; - if ($_REQUEST["debug"]) { + if (!empty($_REQUEST["debug"])) { print "\n*** FIRST ID QUERY ***\n$query\n"; } @@ -1846,7 +1847,7 @@ class Feeds extends Handler_Protected { //if ($_REQUEST["debug"]) print $query; - if ($_REQUEST["debug"]) { + if (!empty($_REQUEST["debug"])) { print "\n*** HEADLINES QUERY ***\n$query\n"; } @@ -1902,7 +1903,7 @@ class Feeds extends Handler_Protected { //if ($_REQUEST["debug"]) print $query; - if ($_REQUEST["debug"]) { + if (!empty($_REQUEST["debug"])) { print "\n*** TAGS QUERY ***\n$query\n"; } @@ -2370,10 +2371,9 @@ class Feeds extends Handler_Protected { function mark_timestamp($label) { - if (!$_REQUEST['timestamps']) + if (empty($_REQUEST['timestamps'])) return; - if (!$this->viewfeed_timestamp) $this->viewfeed_timestamp = hrtime(true); if (!$this->viewfeed_timestamp_last) $this->viewfeed_timestamp_last = hrtime(true); diff --git a/classes/handler/public.php b/classes/handler/public.php index fdf55b1d2..67ad9c5cc 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -669,8 +669,8 @@ class Handler_Public extends Handler { $login = clean($_POST["login"]); $password = clean($_POST["password"]); - $remember_me = clean($_POST["remember_me"]); - $safe_mode = checkbox_to_sql_bool(clean($_POST["safe_mode"])); + $remember_me = clean($_POST["remember_me"] ?? false); + $safe_mode = checkbox_to_sql_bool(clean($_POST["safe_mode"] ?? false)); if ($remember_me) { @session_set_cookie_params(SESSION_COOKIE_LIFETIME); @@ -686,7 +686,7 @@ class Handler_Public extends Handler { } $_SESSION["ref_schema_version"] = get_schema_version(true); - $_SESSION["bw_limit"] = !!clean($_POST["bw_limit"]); + $_SESSION["bw_limit"] = !!clean($_POST["bw_limit"] ?? false); $_SESSION["safe_mode"] = $safe_mode; if (clean($_POST["profile"])) { @@ -729,10 +729,10 @@ class Handler_Public extends Handler { UserHelper::login_sequence(); } - if ($_SESSION["uid"]) { + if (!empty($_SESSION["uid"])) { - $feed_url = trim(clean($_REQUEST["feed_url"])); - $csrf_token = clean($_POST["csrf_token"]); + $feed_url = clean($_REQUEST["feed_url"] ?? ""); + $csrf_token = clean($_POST["csrf_token"] ?? ""); header('Content-Type: text/html; charset=utf-8'); ?> diff --git a/classes/labels.php b/classes/labels.php index 1f27ee25c..786091650 100644 --- a/classes/labels.php +++ b/classes/labels.php @@ -196,6 +196,8 @@ class Labels $sth->execute([$caption, $owner_uid, $fg_color, $bg_color]); $result = $sth->rowCount(); + } else { + $result = false; } if (!$tr_in_progress) $pdo->commit(); diff --git a/classes/logger/sql.php b/classes/logger/sql.php index c1ea16ef9..ad7fdecb2 100755 --- a/classes/logger/sql.php +++ b/classes/logger/sql.php @@ -10,7 +10,7 @@ class Logger_SQL { if ($this->pdo && get_schema_version() > 117) { - $owner_uid = $_SESSION["uid"] ? $_SESSION["uid"] : null; + $owner_uid = $_SESSION["uid"] ?? null; // limit context length, DOMDocument dumps entire XML in here sometimes, which may be huge $context = mb_substr($context, 0, 8192); diff --git a/classes/opml.php b/classes/opml.php index 37e653a39..bc2d4d7b9 100644 --- a/classes/opml.php +++ b/classes/opml.php @@ -272,7 +272,7 @@ class Opml extends Handler_Protected { $doc->preserveWhiteSpace = false; $doc->loadXML($out); - $xpath = new DOMXpath($doc); + $xpath = new DOMXPath($doc); $outlines = $xpath->query("//outline[@title]"); // cleanup empty categories @@ -534,10 +534,11 @@ class Opml extends Handler_Protected { $outlines = $root_node->childNodes; } else { - $xpath = new DOMXpath($doc); + $xpath = new DOMXPath($doc); $outlines = $xpath->query("//opml/body/outline"); $cat_id = 0; + $cat_title = false; } #$this->opml_notice("[CAT] $cat_title id: $cat_id P_id: $parent_id"); @@ -593,7 +594,7 @@ class Opml extends Handler_Protected { } if (is_uploaded_file($_FILES['opml_file']['tmp_name'])) { - $tmp_file = tempnam(CACHE_DIR . '/upload', 'opml'); + $tmp_file = (string)tempnam(CACHE_DIR . '/upload', 'opml'); $result = move_uploaded_file($_FILES['opml_file']['tmp_name'], $tmp_file); @@ -607,13 +608,15 @@ class Opml extends Handler_Protected { return; } + $loaded = false; + if (is_file($tmp_file)) { $doc = new DOMDocument(); libxml_disable_entity_loader(false); $loaded = $doc->load($tmp_file); libxml_disable_entity_loader(true); unlink($tmp_file); - } else if (!$doc) { + } else if (empty($doc)) { print_error(__('Error: unable to find moved OPML file.')); return; } diff --git a/classes/pluginhost.php b/classes/pluginhost.php index 08871af51..bcde12551 100755 --- a/classes/pluginhost.php +++ b/classes/pluginhost.php @@ -128,7 +128,7 @@ class PluginHost { } function get_plugin($name) { - return $this->plugins[strtolower($name)]; + return $this->plugins[strtolower($name)] ?? null; } function run_hooks($type, $method, $args) { @@ -140,11 +140,11 @@ class PluginHost { function add_hook($type, $sender, $priority = 50) { $priority = (int) $priority; - if (!is_array($this->hooks[$type])) { + if (empty($this->hooks[$type])) { $this->hooks[$type] = []; } - if (!is_array($this->hooks[$type][$priority])) { + if (empty($this->hooks[$type][$priority])) { $this->hooks[$type][$priority] = []; } @@ -277,7 +277,7 @@ class PluginHost { function is_system($plugin) { $about = $plugin->about(); - return @$about[3]; + return $about[3] ?? false; } // only system plugins are allowed to modify routing @@ -307,7 +307,7 @@ class PluginHost { $handler = str_replace("-", "_", strtolower($handler)); $method = strtolower($method); - if (is_array($this->handlers[$handler])) { + if (isset($this->handlers[$handler])) { if (isset($this->handlers[$handler]["*"])) { return $this->handlers[$handler]["*"]; } else { @@ -390,13 +390,13 @@ class PluginHost { if ($sth->fetch()) { $sth = $this->pdo_data->prepare("UPDATE ttrss_plugin_storage SET content = ? WHERE owner_uid= ? AND name = ?"); - $sth->execute([(string)$content, $this->owner_uid, $plugin]); + $sth->execute([$content, $this->owner_uid, $plugin]); } else { $sth = $this->pdo_data->prepare("INSERT INTO ttrss_plugin_storage (name,owner_uid,content) VALUES (?, ?, ?)"); - $sth->execute([$plugin, $this->owner_uid, (string)$content]); + $sth->execute([$plugin, $this->owner_uid, $content]); } $this->pdo_data->commit(); @@ -429,9 +429,7 @@ class PluginHost { function get_all($sender) { $idx = get_class($sender); - $data = $this->storage[$idx]; - - return $data ? $data : []; + return $this->storage[$idx] ?? []; } function clear_data($sender) { @@ -461,7 +459,7 @@ class PluginHost { } function get_feeds($cat_id) { - return $this->feeds[$cat_id]; + return $this->feeds[$cat_id] ?? []; } // convert feed_id (e.g. -129) to pfeed_id first diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index 88c5b7f0e..474f1e1db 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -42,14 +42,14 @@ class Pref_Feeds extends Handler_Protected { private function get_category_items($cat_id) { - if (clean($_REQUEST['mode']) != 2) - $search = $_SESSION["prefs_feed_search"]; + if (clean($_REQUEST['mode'] ?? 0) != 2) + $search = $_SESSION["prefs_feed_search"] ?? ""; else $search = ""; // first one is set by API - $show_empty_cats = clean($_REQUEST['force_show_empty']) || - (clean($_REQUEST['mode']) != 2 && !$search); + $show_empty_cats = clean($_REQUEST['force_show_empty'] ?? false) || + (clean($_REQUEST['mode'] ?? 0) != 2 && !$search); $items = array(); @@ -117,8 +117,8 @@ class Pref_Feeds extends Handler_Protected { function makefeedtree() { - if (clean($_REQUEST['mode']) != 2) - $search = $_SESSION["prefs_feed_search"]; + if (clean($_REQUEST['mode'] ?? 0) != 2) + $search = $_SESSION["prefs_feed_search"] ?? ""; else $search = ""; @@ -131,7 +131,7 @@ class Pref_Feeds extends Handler_Protected { $enable_cats = get_pref('ENABLE_FEED_CATS'); - if (clean($_REQUEST['mode']) == 2) { + if (clean($_REQUEST['mode'] ?? 0) == 2) { if ($enable_cats) { $cat = $this->feedlist_init_cat(-1); @@ -208,8 +208,8 @@ class Pref_Feeds extends Handler_Protected { } if ($enable_cats) { - $show_empty_cats = clean($_REQUEST['force_show_empty']) || - (clean($_REQUEST['mode']) != 2 && !$search); + $show_empty_cats = clean($_REQUEST['force_show_empty'] ?? false) || + (clean($_REQUEST['mode'] ?? 0) != 2 && !$search); $sth = $this->pdo->prepare("SELECT id, title FROM ttrss_feed_categories WHERE owner_uid = ? AND parent_cat IS NULL ORDER BY order_id, title"); @@ -320,7 +320,7 @@ class Pref_Feeds extends Handler_Protected { $fl['identifier'] = 'id'; $fl['label'] = 'name'; - if (clean($_REQUEST['mode']) != 2) { + if (clean($_REQUEST['mode'] ?? 0) != 2) { $fl['items'] = array($root); } else { $fl['items'] = $root['items']; @@ -551,11 +551,9 @@ class Pref_Feeds extends Handler_Protected { regExp='^(http|https)://.*' style='width : 300px' name='feed_url' value=\"$feed_url\">"; - $last_error = $row["last_error"]; - - if ($last_error) { + if (!empty($row["last_error"])) { print " <i class=\"material-icons\" - title=\"".htmlspecialchars($last_error)."\">error</i>"; + title=\"".htmlspecialchars($row["last_error"])."\">error</i>"; } print "</fieldset>"; @@ -996,16 +994,16 @@ class Pref_Feeds extends Handler_Protected { function editsaveops($batch) { - $feed_title = trim(clean($_POST["title"])); - $feed_url = trim(clean($_POST["feed_url"])); - $site_url = trim(clean($_POST["site_url"])); + $feed_title = clean($_POST["title"]); + $feed_url = clean($_POST["feed_url"]); + $site_url = clean($_POST["site_url"]); $upd_intl = (int) clean($_POST["update_interval"]); $purge_intl = (int) clean($_POST["purge_interval"]); $feed_id = (int) clean($_POST["id"]); /* editSave */ $feed_ids = explode(",", clean($_POST["ids"])); /* batchEditSave */ $cat_id = (int) clean($_POST["cat_id"]); - $auth_login = trim(clean($_POST["auth_login"])); - $auth_pass = trim(clean($_POST["auth_pass"])); + $auth_login = clean($_POST["auth_login"]); + $auth_pass = clean($_POST["auth_pass"]); $private = checkbox_to_sql_bool(clean($_POST["private"])); $include_in_digest = checkbox_to_sql_bool( clean($_POST["include_in_digest"])); @@ -1019,7 +1017,7 @@ class Pref_Feeds extends Handler_Protected { $mark_unread_on_update = checkbox_to_sql_bool( clean($_POST["mark_unread_on_update"])); - $feed_language = trim(clean($_POST["feed_language"])); + $feed_language = clean($_POST["feed_language"]); if (!$batch) { if (clean($_POST["need_auth"]) !== 'on') { @@ -1193,7 +1191,7 @@ class Pref_Feeds extends Handler_Protected { } function addCat() { - $feed_cat = trim(clean($_REQUEST["cat"])); + $feed_cat = clean($_REQUEST["cat"]); Feeds::add_feed_category($feed_cat); } @@ -1228,12 +1226,12 @@ class Pref_Feeds extends Handler_Protected { onclick=\"dijit.byId('feedTree').showInactiveFeeds()\">" . __("Inactive feeds") . "</button>"; - $feed_search = clean($_REQUEST["search"]); + $feed_search = clean($_REQUEST["search"] ?? ""); if (array_key_exists("search", $_REQUEST)) { $_SESSION["prefs_feed_search"] = $feed_search; } else { - $feed_search = $_SESSION["prefs_feed_search"]; + $feed_search = $_SESSION["prefs_feed_search"] ?? ""; } print '<div dojoType="dijit.layout.BorderContainer" gutters="false">'; @@ -1689,7 +1687,7 @@ class Pref_Feeds extends Handler_Protected { $cat_id = clean($_REQUEST['cat']); $feeds = explode("\n", clean($_REQUEST['feeds'])); $login = clean($_REQUEST['login']); - $pass = trim(clean($_REQUEST['pass'])); + $pass = clean($_REQUEST['pass']); $csth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE feed_url = ? AND owner_uid = ?"); @@ -1756,8 +1754,8 @@ class Pref_Feeds extends Handler_Protected { private function calculate_children_count($cat) { $c = 0; - foreach ($cat['items'] as $child) { - if ($child['type'] == 'category') { + foreach ($cat['items'] ?? [] as $child) { + if ($child['type'] ?? '' == 'category') { $c += $this->calculate_children_count($child); } else { $c += 1; diff --git a/classes/pref/filters.php b/classes/pref/filters.php index 70b7d0326..993b35c11 100755 --- a/classes/pref/filters.php +++ b/classes/pref/filters.php @@ -241,7 +241,7 @@ class Pref_Filters extends Handler_Protected { $root['enabled'] = true; $root['items'] = array(); - $filter_search = $_SESSION["prefs_filter_search"]; + $filter_search = ($_SESSION["prefs_filter_search"] ?? ""); $sth = $this->pdo->prepare("SELECT *, (SELECT action_param FROM ttrss_filters2_actions @@ -599,9 +599,9 @@ class Pref_Filters extends Handler_Protected { function editSave() { $filter_id = clean($_REQUEST["id"]); - $enabled = checkbox_to_sql_bool(clean($_REQUEST["enabled"])); + $enabled = checkbox_to_sql_bool(clean($_REQUEST["enabled"] ?? false)); $match_any_rule = checkbox_to_sql_bool(clean($_REQUEST["match_any_rule"])); - $inverse = checkbox_to_sql_bool(clean($_REQUEST["inverse"])); + $inverse = checkbox_to_sql_bool(clean($_REQUEST["inverse"] ?? false)); $title = clean($_REQUEST["title"]); $this->pdo->beginTransaction(); @@ -638,8 +638,8 @@ class Pref_Filters extends Handler_Protected { $sth = $this->pdo->prepare("DELETE FROM ttrss_filters2_actions WHERE filter_id = ?"); $sth->execute([$filter_id]); - if (!is_array(clean($_REQUEST["rule"]))) $_REQUEST["rule"] = []; - if (!is_array(clean($_REQUEST["action"]))) $_REQUEST["action"] = []; + if (!is_array(clean($_REQUEST["rule"] ?? ""))) $_REQUEST["rule"] = []; + if (!is_array(clean($_REQUEST["action"] ?? ""))) $_REQUEST["action"] = []; if ($filter_id) { /* create rules */ @@ -740,7 +740,7 @@ class Pref_Filters extends Handler_Protected { $filter_search = clean($_REQUEST["search"]); $_SESSION["prefs_filter_search"] = $filter_search; } else { - $filter_search = $_SESSION["prefs_filter_search"]; + $filter_search = ($_SESSION["prefs_filter_search"] ?? ""); } print "<div dojoType='dijit.layout.BorderContainer' gutters='false'>"; diff --git a/classes/pref/labels.php b/classes/pref/labels.php index ec9667441..b4d1236b2 100644 --- a/classes/pref/labels.php +++ b/classes/pref/labels.php @@ -166,7 +166,7 @@ class Pref_Labels extends Handler_Protected { function save() { $id = clean($_REQUEST["id"]); - $caption = trim(clean($_REQUEST["caption"])); + $caption = clean($_REQUEST["caption"]); $this->pdo->beginTransaction(); diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 55a15efb8..907c639b3 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -321,7 +321,7 @@ class Pref_Prefs extends Handler_Protected { print "<input dojoType='dijit.form.ValidationTextBox' name='email' required='1' value='$email'>"; print "</fieldset>"; - if (!SINGLE_USER_MODE && !$_SESSION["hide_hello"]) { + if (!SINGLE_USER_MODE && !empty($_SESSION["hide_hello"])) { $access_level = $row["access_level"]; print "<fieldset>"; @@ -595,7 +595,7 @@ class Pref_Prefs extends Handler_Protected { print '<div dojoType="dijit.layout.ContentPane" region="center" style="overflow-y : auto">'; - $profile = $_SESSION["profile"]; + $profile = $_SESSION["profile"] ?? null; if ($profile) { print_notice(__("Some preferences are only available in default profile.")); @@ -916,7 +916,7 @@ class Pref_Prefs extends Handler_Protected { foreach ($tmppluginhost->get_plugins() as $name => $plugin) { $about = $plugin->about(); - if ($about[3]) { + if ($about[3] ?? false) { if (in_array($name, $system_enabled)) { $checked = "checked='1'"; } else { @@ -930,7 +930,7 @@ class Pref_Prefs extends Handler_Protected { dojoType='dijit.form.CheckBox' $checked type='checkbox'> ".htmlspecialchars($about[1]). "</label>"; - if (@$about[4]) { + if ($about[4] ?? false) { print "<button dojoType='dijit.form.Button' class='alt-info' onclick='window.open(\"".htmlspecialchars($about[4])."\")'> <i class='material-icons'>open_in_new</i> ".__("More info...")."</button>"; @@ -950,7 +950,7 @@ class Pref_Prefs extends Handler_Protected { foreach ($tmppluginhost->get_plugins() as $name => $plugin) { $about = $plugin->about(); - if (!$about[3]) { + if ($about[3] ?? true) { $checked = ""; $disabled = ""; @@ -976,7 +976,7 @@ class Pref_Prefs extends Handler_Protected { } } - if (@$about[4]) { + if ($about[4] ?? false) { print " <button dojoType='dijit.form.Button' class='alt-info' onclick='window.open(\"".htmlspecialchars($about[4])."\")'> <i class='material-icons'>open_in_new</i> ".__("More info...")."</button>"; diff --git a/classes/pref/system.php b/classes/pref/system.php index 89052c6e3..33a567df5 100644 --- a/classes/pref/system.php +++ b/classes/pref/system.php @@ -2,6 +2,8 @@ class Pref_System extends Handler_Protected { + private $log_page_limit = 15; + function before($method) { if (parent::before($method)) { if ($_SESSION["access_level"] < 10) { @@ -23,101 +25,135 @@ class Pref_System extends Handler_Protected { $this->pdo->query("DELETE FROM ttrss_error_log"); } - function index() { + private function log_viewer(int $page, int $severity) { + $errno_values = []; - $severity = isset($_REQUEST["severity"]) ? (int) clean($_REQUEST["severity"]) : E_USER_WARNING; + switch ($severity) { + case E_USER_ERROR: + $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE ]; + break; + case E_USER_WARNING: + $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE, E_WARNING, E_USER_WARNING, E_DEPRECATED, E_USER_DEPRECATED ]; + break; + } - print "<div dojoType='dijit.layout.AccordionContainer' region='center'>"; - print "<div dojoType='dijit.layout.AccordionPane' style='padding : 0' - title='<i class=\"material-icons\">report</i> ".__('Event Log')."'>"; + if (count($errno_values) > 0) { + $errno_qmarks = arr_qmarks($errno_values); + $errno_filter_qpart = "errno IN ($errno_qmarks)"; + } else { + $errno_filter_qpart = "true"; + } - if (LOG_DESTINATION == "sql") { + $limit = $this->log_page_limit; + $offset = $limit * $page; - print "<div dojoType='dijit.layout.BorderContainer' gutters='false'>"; + $sth = $this->pdo->prepare("SELECT + COUNT(id) AS total_pages + FROM + ttrss_error_log + WHERE + $errno_filter_qpart"); - print "<div region='top' dojoType='fox.Toolbar'>"; + $sth->execute($errno_values); - print "<button dojoType='dijit.form.Button' - onclick='Helpers.updateEventLog()'>".__('Refresh')."</button>"; + if ($res = $sth->fetch()) { + $total_pages = (int)($res["total_pages"] / $limit); + } else { + $total_pages = 0; + } - print "<button dojoType='dijit.form.Button' - onclick='Helpers.clearEventLog()'>".__('Clear')."</button>"; + print "<div dojoType='dijit.layout.BorderContainer' gutters='false'>"; - print "<div class='pull-right'>"; + print "<div region='top' dojoType='fox.Toolbar'>"; - print __("Severity:") . " "; - print_select_hash("severity", $severity, - [ - E_USER_ERROR => __("Errors"), - E_USER_WARNING => __("Warnings"), - E_USER_NOTICE => __("Everything") - ], 'dojoType="fox.form.Select" onchange="Helpers.updateEventLog()"'); + print "<button dojoType='dijit.form.Button' + onclick='Helpers.EventLog.refresh()'>".__('Refresh')."</button>"; - print "</div>"; # pull-right + print "<button dojoType='dijit.form.Button' + onclick='Helpers.EventLog.prevPage()'>".__('<<')."</button>"; - print "</div>"; # toolbar + print "<button dojoType='dijit.form.Button' disabled>".T_sprintf('Page %d of %d', $page+1, $total_pages+1)."</button>"; - print '<div style="padding : 0px" dojoType="dijit.layout.ContentPane" region="center">'; + $next_page_disabled = $page >= $total_pages ? "disabled" : ""; - print "<table width='100%' cellspacing='10' class='prefErrorLog'>"; + print "<button dojoType='dijit.form.Button' $next_page_disabled + onclick='Helpers.EventLog.nextPage()'>".__('>>')."</button>"; - print "<tr class='title'> - <td width='5%'>".__("Error")."</td> - <td>".__("Filename")."</td> - <td>".__("Message")."</td> - <td width='5%'>".__("User")."</td> - <td width='5%'>".__("Date")."</td> - </tr>"; + print "<button dojoType='dijit.form.Button' + onclick='Helpers.EventLog.clear()'>".__('Clear')."</button>"; - $errno_values = []; + print "<div class='pull-right'>"; - switch ($severity) { - case E_USER_ERROR: - $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE ]; - break; - case E_USER_WARNING: - $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE, E_WARNING, E_USER_WARNING, E_DEPRECATED, E_USER_DEPRECATED ]; - break; - } + print __("Severity:") . " "; + print_select_hash("severity", $severity, + [ + E_USER_ERROR => __("Errors"), + E_USER_WARNING => __("Warnings"), + E_USER_NOTICE => __("Everything") + ], 'dojoType="fox.form.Select" onchange="Helpers.EventLog.refresh()"'); - if (count($errno_values) > 0) { - $errno_qmarks = arr_qmarks($errno_values); - $errno_filter_qpart = "errno IN ($errno_qmarks)"; - } else { - $errno_filter_qpart = "true"; - } + print "</div>"; # pull-right + + print "</div>"; # toolbar - $sth = $this->pdo->prepare("SELECT - errno, errstr, filename, lineno, created_at, login, context - FROM - ttrss_error_log LEFT JOIN ttrss_users ON (owner_uid = ttrss_users.id) - WHERE - $errno_filter_qpart - ORDER BY - ttrss_error_log.id DESC - LIMIT 100"); + print '<div style="padding : 0px" dojoType="dijit.layout.ContentPane" region="center">'; - $sth->execute($errno_values); + print "<table width='100%' class='event-log'>"; - while ($line = $sth->fetch()) { - print "<tr>"; + print "<tr class='title'> + <td width='5%'>".__("Error")."</td> + <td>".__("Filename")."</td> + <td>".__("Message")."</td> + <td width='5%'>".__("User")."</td> + <td width='5%'>".__("Date")."</td> + </tr>"; - foreach ($line as $k => $v) { - $line[$k] = htmlspecialchars($v); - } + $sth = $this->pdo->prepare("SELECT + errno, errstr, filename, lineno, created_at, login, context + FROM + ttrss_error_log LEFT JOIN ttrss_users ON (owner_uid = ttrss_users.id) + WHERE + $errno_filter_qpart + ORDER BY + ttrss_error_log.id DESC + LIMIT $limit OFFSET $offset"); - print "<td class='errno'>" . Logger::$errornames[$line["errno"]] . " (" . $line["errno"] . ")</td>"; - print "<td class='filename'>" . $line["filename"] . ":" . $line["lineno"] . "</td>"; - print "<td class='errstr'>" . $line["errstr"] . "<hr/>" . nl2br($line["context"]) . "</td>"; - print "<td class='login'>" . $line["login"] . "</td>"; + $sth->execute($errno_values); - print "<td class='timestamp'>" . - TimeHelper::make_local_datetime($line["created_at"], false) . "</td>"; + while ($line = $sth->fetch()) { + print "<tr>"; - print "</tr>"; + foreach ($line as $k => $v) { + $line[$k] = htmlspecialchars($v); } - print "</table>"; + print "<td class='errno'>" . Logger::$errornames[$line["errno"]] . " (" . $line["errno"] . ")</td>"; + print "<td class='filename'>" . $line["filename"] . ":" . $line["lineno"] . "</td>"; + print "<td class='errstr'>" . $line["errstr"] . "\n" . $line["context"] . "</td>"; + print "<td class='login'>" . $line["login"] . "</td>"; + + print "<td class='timestamp'>" . + TimeHelper::make_local_datetime($line["created_at"], false) . "</td>"; + + print "</tr>"; + } + + print "</table>"; + } + + function index() { + + $severity = (int) ($_REQUEST["severity"] ?? E_USER_WARNING); + $page = (int) ($_REQUEST["page"] ?? 0); + + print "<div dojoType='dijit.layout.AccordionContainer' region='center'>"; + print "<div dojoType='dijit.layout.AccordionPane' style='padding : 0' + title='<i class=\"material-icons\">report</i> ".__('Event Log')."'>"; + + if (LOG_DESTINATION == "sql") { + + $this->log_viewer($page, $severity); + } else { print_notice("Please set LOG_DESTINATION to 'sql' in config.php to enable database logging."); } diff --git a/classes/pref/users.php b/classes/pref/users.php index 5ec7aa2e6..4d804b8de 100644 --- a/classes/pref/users.php +++ b/classes/pref/users.php @@ -191,10 +191,10 @@ class Pref_Users extends Handler_Protected { } function editSave() { - $login = trim(clean($_REQUEST["login"])); + $login = clean($_REQUEST["login"]); $uid = clean($_REQUEST["id"]); $access_level = (int) clean($_REQUEST["access_level"]); - $email = trim(clean($_REQUEST["email"])); + $email = clean($_REQUEST["email"]); $password = clean($_REQUEST["password"]); if ($password) { @@ -230,7 +230,7 @@ class Pref_Users extends Handler_Protected { } function add() { - $login = trim(clean($_REQUEST["login"])); + $login = clean($_REQUEST["login"]); $tmp_user_pwd = make_password(); $salt = substr(bin2hex(get_random_bytes(125)), 0, 250); $pwd_hash = encrypt_password($tmp_user_pwd, $salt, true); @@ -315,12 +315,12 @@ class Pref_Users extends Handler_Protected { print "<div style='padding : 0px' dojoType='dijit.layout.ContentPane' region='top'>"; print "<div dojoType='fox.Toolbar'>"; - $user_search = trim(clean($_REQUEST["search"])); + $user_search = clean($_REQUEST["search"] ?? ""); if (array_key_exists("search", $_REQUEST)) { $_SESSION["prefs_user_search"] = $user_search; } else { - $user_search = $_SESSION["prefs_user_search"]; + $user_search = ($_SESSION["prefs_user_search"] ?? ""); } print "<div style='float : right; padding-right : 4px;'> @@ -330,7 +330,7 @@ class Pref_Users extends Handler_Protected { __('Search')."</button> </div>"; - $sort = clean($_REQUEST["sort"]); + $sort = clean($_REQUEST["sort"] ?? ""); if (!$sort || $sort == "undefined") { $sort = "login"; @@ -339,9 +339,9 @@ class Pref_Users extends Handler_Protected { print "<div dojoType='fox.form.DropDownButton'>". "<span>" . __('Select')."</span>"; print "<div dojoType='dijit.Menu' style='display: none'>"; - print "<div onclick=\"Tables.select('prefUserList', true)\" + print "<div onclick=\"Tables.select('users-list', true)\" dojoType='dijit.MenuItem'>".__('All')."</div>"; - print "<div onclick=\"Tables.select('prefUserList', false)\" + print "<div onclick=\"Tables.select('users-list', false)\" dojoType='dijit.MenuItem'>".__('None')."</div>"; print "</div></div>"; @@ -380,7 +380,7 @@ class Pref_Users extends Handler_Protected { ORDER BY $sort"); $sth->execute([":search" => $user_search ? "%$user_search%" : ""]); - print "<p><table width='100%' cellspacing='0' class='prefUserList' id='prefUserList'>"; + print "<table width='100%' class='users-list' id='users-list'>"; print "<tr class='title'> <td align='center' width='5%'> </td> @@ -457,9 +457,12 @@ class Pref_Users extends Handler_Protected { } static function logout_user() { - @session_destroy(); + if (session_status() === PHP_SESSION_ACTIVE) + session_destroy(); + if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time()-42000, '/'); + } session_commit(); } diff --git a/classes/rpc.php b/classes/rpc.php index 0e881b3ce..9f86c9401 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -15,7 +15,7 @@ class RPC extends Handler_Protected { } function remprofiles() { - $ids = explode(",", trim(clean($_REQUEST["ids"]))); + $ids = explode(",", clean($_REQUEST["ids"])); foreach ($ids as $id) { if ($_SESSION["profile"] != $id) { @@ -28,7 +28,7 @@ class RPC extends Handler_Protected { // Silent function addprofile() { - $title = trim(clean($_REQUEST["title"])); + $title = clean($_REQUEST["title"]); if ($title) { $this->pdo->beginTransaction(); @@ -63,7 +63,7 @@ class RPC extends Handler_Protected { function saveprofile() { $id = clean($_REQUEST["id"]); - $title = trim(clean($_REQUEST["value"])); + $title = clean($_REQUEST["value"]); if ($id == 0) { print __("Default profile"); @@ -85,7 +85,7 @@ class RPC extends Handler_Protected { $cat = clean($_REQUEST['cat']); $need_auth = isset($_REQUEST['need_auth']); $login = $need_auth ? clean($_REQUEST['login']) : ''; - $pass = $need_auth ? trim(clean($_REQUEST['pass'])) : ''; + $pass = $need_auth ? clean($_REQUEST['pass']) : ''; $rc = Feeds::subscribe_to_feed($feed, $cat, $login, $pass); @@ -244,7 +244,7 @@ class RPC extends Handler_Protected { function setpanelmode() { $wide = (int) clean($_REQUEST["wide"]); - setcookie("ttrss_widescreen", $wide, + setcookie("ttrss_widescreen", (string)$wide, time() + COOKIE_LIFETIME_LONG); print json_encode(array("wide" => $wide)); @@ -462,7 +462,7 @@ class RPC extends Handler_Protected { $params["default_view_order_by"] = get_pref("_DEFAULT_VIEW_ORDER_BY"); $params["bw_limit"] = (int) $_SESSION["bw_limit"]; $params["is_default_pw"] = Pref_Prefs::isdefaultpassword(); - $params["label_base_index"] = (int) LABEL_BASE_INDEX; + $params["label_base_index"] = LABEL_BASE_INDEX; $theme = get_pref( "USER_CSS_THEME", false, false); $params["theme"] = theme_exists($theme) ? $theme : ""; @@ -488,9 +488,9 @@ class RPC extends Handler_Protected { $params["hotkeys"] = $this->get_hotkeys_map(); - $params["widescreen"] = (int) $_COOKIE["ttrss_widescreen"]; + $params["widescreen"] = (int) ($_COOKIE["ttrss_widescreen"] ?? 0); - $params['simple_update'] = defined('SIMPLE_UPDATE_MODE') && SIMPLE_UPDATE_MODE; + $params['simple_update'] = SIMPLE_UPDATE_MODE; $params["icon_indicator_white"] = $this->image_to_base64("images/indicator_white.gif"); @@ -503,7 +503,7 @@ class RPC extends Handler_Protected { if (file_exists($filename)) { $ext = pathinfo($filename, PATHINFO_EXTENSION); - return "data:image/$ext;base64," . base64_encode(file_get_contents($filename)); + return "data:image/$ext;base64," . base64_encode((string)file_get_contents($filename)); } else { return ""; } @@ -546,7 +546,7 @@ class RPC extends Handler_Protected { $data['daemon_is_running'] = (int) file_is_locked("update_daemon.lock"); - if (time() - $_SESSION["daemon_stamp_check"] > 30) { + if (time() - ($_SESSION["daemon_stamp_check"] ?? 0) > 30) { $stamp = (int) @file_get_contents(LOCK_DIRECTORY . "/update_daemon.stamp"); @@ -719,7 +719,7 @@ class RPC extends Handler_Protected { $prefixes = array(); foreach (array_keys($hotkeys) as $hotkey) { - $pair = explode(" ", $hotkey, 2); + $pair = explode(" ", (string)$hotkey, 2); if (count($pair) > 1 && !in_array($pair[0], $prefixes)) { array_push($prefixes, $pair[0]); diff --git a/classes/rssutils.php b/classes/rssutils.php index 96f7b7c36..45cddb200 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -10,7 +10,8 @@ class RSSUtils { continue; if ($k != "feed" && isset($v)) { - $x = strip_tags(is_array($v) ? implode(",", $v) : $v); + $x = strip_tags( + is_array($v) ? implode(",", array_keys($v)) : $v); $tmp .= sha1("$k:" . sha1($x)); } @@ -590,12 +591,12 @@ class RSSUtils { * the icon avgcolor again (unless the icon got updated) */ $favicon_file = ICONS_DIR . "/$feed.ico"; - $favicon_modified = @filemtime($favicon_file); + $favicon_modified = file_exists($favicon_file) ? filemtime($favicon_file) : -1; Debug::log("checking favicon...", Debug::$LOG_VERBOSE); self::check_feed_favicon($site_url, $feed); - $favicon_modified_new = @filemtime($favicon_file); + $favicon_modified_new = file_exists($favicon_file) ? filemtime($favicon_file) : -1; if ($favicon_modified_new > $favicon_modified) $favicon_avg_color = ''; @@ -1414,7 +1415,7 @@ class RSSUtils { * @param string query * @return array params */ - static function convertUrlQuery($query) { + /* static function convertUrlQuery($query) { $queryParts = explode('&', $query); $params = array(); @@ -1425,7 +1426,7 @@ class RSSUtils { } return $params; - } + } */ static function get_article_filters($filters, $title, $content, $link, $author, $tags, &$matched_rules = false, &$matched_filters = false) { $matches = array(); @@ -1434,14 +1435,16 @@ class RSSUtils { $match_any_rule = $filter["match_any_rule"]; $inverse = $filter["inverse"]; $filter_match = false; + $last_processed_rule = false; foreach ($filter["rules"] as $rule) { $match = false; - $reg_exp = str_replace('/', '\/', $rule["reg_exp"]); + $reg_exp = str_replace('/', '\/', (string)$rule["reg_exp"]); $reg_exp = str_replace("\n", "", $reg_exp); // reg_exp may be formatted with CRs now because of textarea, we need to strip those $rule_inverse = $rule["inverse"]; + $last_processed_rule = $rule; - if (!$reg_exp) + if (empty($reg_exp)) continue; switch ($rule["type"]) { @@ -1450,13 +1453,13 @@ class RSSUtils { break; case "content": // we don't need to deal with multiline regexps - $content = preg_replace("/[\r\n\t]/", "", $content); + $content = (string)preg_replace("/[\r\n\t]/", "", $content); $match = @preg_match("/$reg_exp/iu", $content); break; case "both": // we don't need to deal with multiline regexps - $content = preg_replace("/[\r\n\t]/", "", $content); + $content = (string)preg_replace("/[\r\n\t]/", "", $content); $match = (@preg_match("/$reg_exp/iu", $title) || @preg_match("/$reg_exp/iu", $content)); break; @@ -1494,7 +1497,7 @@ class RSSUtils { if ($inverse) $filter_match = !$filter_match; if ($filter_match) { - if (is_array($matched_rules)) array_push($matched_rules, $rule); + if (is_array($matched_rules)) array_push($matched_rules, $last_processed_rule); if (is_array($matched_filters)) array_push($matched_filters, $filter); foreach ($filter["actions"] AS $action) { @@ -1580,11 +1583,11 @@ class RSSUtils { $pdo->beginTransaction(); - $days = (int) DAEMON_UNSUCCESSFUL_DAYS_LIMIT; + $days = DAEMON_UNSUCCESSFUL_DAYS_LIMIT; if (DB_TYPE == "pgsql") { $interval_query = "last_successful_update < NOW() - INTERVAL '$days days' AND last_updated > NOW() - INTERVAL '1 days'"; - } else if (DB_TYPE == "mysql") { + } else /* if (DB_TYPE == "mysql") */ { $interval_query = "last_successful_update < DATE_SUB(NOW(), INTERVAL $days DAY) AND last_updated > DATE_SUB(NOW(), INTERVAL 1 DAY)"; } diff --git a/classes/sanitizer.php b/classes/sanitizer.php index 9f3bfada0..5a054c3b0 100644 --- a/classes/sanitizer.php +++ b/classes/sanitizer.php @@ -54,7 +54,9 @@ class Sanitizer { } public static function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) { - if (!$owner) $owner = $_SESSION["uid"]; + + if (!$owner && isset($_SESSION["uid"])) + $owner = $_SESSION["uid"]; $res = trim($str); if (!$res) return ''; @@ -97,7 +99,7 @@ class Sanitizer { } if ($entry->hasAttribute('src') && - ($owner && get_pref("STRIP_IMAGES", $owner)) || $force_remove_images || $_SESSION["bw_limit"]) { + ($owner && get_pref("STRIP_IMAGES", $owner)) || $force_remove_images || ($_SESSION["bw_limit"] ?? false)) { $p = $doc->createElement('p'); @@ -147,7 +149,7 @@ class Sanitizer { 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'wbr', 'video', 'xml:namespace' ); - if ($_SESSION['hasSandbox']) $allowed_elements[] = 'iframe'; + if ($_SESSION['hasSandbox'] ?? false) $allowed_elements[] = 'iframe'; $disallowed_attributes = array('id', 'style', 'class', 'width', 'height', 'allow'); @@ -186,16 +188,16 @@ class Sanitizer { $text = $child->textContent; while (($pos = mb_stripos($text, $word)) !== false) { - $fragment->appendChild(new DomText(mb_substr($text, 0, $pos))); - $word = mb_substr($text, $pos, mb_strlen($word)); + $fragment->appendChild(new DOMText(mb_substr($text, 0, (int)$pos))); + $word = mb_substr($text, (int)$pos, mb_strlen($word)); $highlight = $doc->createElement('span'); - $highlight->appendChild(new DomText($word)); + $highlight->appendChild(new DOMText($word)); $highlight->setAttribute('class', 'highlight'); $fragment->appendChild($highlight); $text = mb_substr($text, $pos + mb_strlen($word)); } - if (!empty($text)) $fragment->appendChild(new DomText($text)); + if (!empty($text)) $fragment->appendChild(new DOMText($text)); $child->parentNode->replaceChild($fragment, $child); } diff --git a/classes/timehelper.php b/classes/timehelper.php index ce9e35f3e..7dff71669 100644 --- a/classes/timehelper.php +++ b/classes/timehelper.php @@ -49,7 +49,7 @@ class TimeHelper { $tz_offset = $user_tz->getOffset($dt); } else { - $tz_offset = (int) -$_SESSION["clientTzOffset"]; + $tz_offset = (int) -($_SESSION["clientTzOffset"] ?? 0); } $user_timestamp = $dt->format('U') + $tz_offset; @@ -82,7 +82,8 @@ class TimeHelper { } $dt = new DateTime(date('Y-m-d H:i:s', $timestamp), $source_tz); - return $dt->format('U') + $dest_tz->getOffset($dt); + + return (int)$dt->format('U') + $dest_tz->getOffset($dt); } } diff --git a/classes/urlhelper.php b/classes/urlhelper.php index fec36de51..8717d02c3 100644 --- a/classes/urlhelper.php +++ b/classes/urlhelper.php @@ -22,7 +22,7 @@ class UrlHelper { $rel_parts = parse_url($rel_url); - if ($rel_parts['host'] && $rel_parts['scheme']) { + if (!empty($rel_parts['host']) && !empty($rel_parts['scheme'])) { return self::validate($rel_url); } else if (strpos($rel_url, "//") === 0) { # protocol-relative URL (rare but they exist) @@ -61,7 +61,7 @@ class UrlHelper { // this isn't really necessary because filter_var(... FILTER_VALIDATE_URL) requires host and scheme // as per https://php.watch/versions/7.3/filter-var-flag-deprecation but it might save time - if (!$tokens['host']) + if (empty($tokens['host'])) return false; if (!in_array(strtolower($tokens['scheme']), ['http', 'https'])) @@ -82,7 +82,7 @@ class UrlHelper { // (used for validation only, we actually request the original URL, in case of urlencode breaking it) $tokens_filter_var = $tokens; - if ($tokens['path']) { + if ($tokens['path'] ?? false) { $tokens_filter_var['path'] = implode("/", array_map("rawurlencode", array_map("rawurldecode", @@ -96,7 +96,7 @@ class UrlHelper { return false; if ($extended_filtering) { - if (!in_array($tokens['port'], [80, 443, ''])) + if (!in_array($tokens['port'] ?? '', [80, 443, ''])) return false; if (strtolower($tokens['host']) == 'localhost' || $tokens['host'] == '::1' || strpos($tokens['host'], '127.') === 0) @@ -166,7 +166,6 @@ class UrlHelper { global $fetch_effective_url; global $fetch_effective_ip_addr; global $fetch_curl_used; - global $fetch_domain_hits; $fetch_last_error = false; $fetch_last_error_code = -1; @@ -177,9 +176,6 @@ class UrlHelper { $fetch_effective_url = ""; $fetch_effective_ip_addr = ""; - if (!is_array($fetch_domain_hits)) - $fetch_domain_hits = []; - if (!is_array($options)) { // falling back on compatibility shim @@ -235,19 +231,14 @@ class UrlHelper { return false; } - $fetch_domain_hits[$url_host] += 1; - - /*if ($fetch_domain_hits[$url_host] > MAX_FETCH_REQUESTS_PER_HOST) { - user_error("Exceeded fetch request quota for $url_host: " . $fetch_domain_hits[$url_host], E_USER_WARNING); - #return false; - }*/ - if (!defined('NO_CURL') && function_exists('curl_init') && !ini_get("open_basedir")) { $fetch_curl_used = true; $ch = curl_init($url); + if (!$ch) return false; + $curl_http_headers = []; if ($last_modified && !$post_query) @@ -372,7 +363,7 @@ class UrlHelper { $is_gzipped = RSSUtils::is_gzipped($contents); - if ($is_gzipped) { + if ($is_gzipped && is_string($contents)) { $tmp = @gzdecode($contents); if ($tmp) $contents = $tmp; @@ -444,29 +435,27 @@ class UrlHelper { $data = @file_get_contents($url, false, $context); - if (isset($http_response_header) && is_array($http_response_header)) { - foreach ($http_response_header as $header) { - if (strstr($header, ": ") !== false) { - list ($key, $value) = explode(": ", $header); - - $key = strtolower($key); - - if ($key == 'content-type') { - $fetch_last_content_type = $value; - // don't abort here b/c there might be more than one - // e.g. if we were being redirected -- last one is the right one - } else if ($key == 'last-modified') { - $fetch_last_modified = $value; - } else if ($key == 'location') { - $fetch_effective_url = $value; - } - } + foreach ($http_response_header as $header) { + if (strstr($header, ": ") !== false) { + list ($key, $value) = explode(": ", $header); - if (substr(strtolower($header), 0, 7) == 'http/1.') { - $fetch_last_error_code = (int) substr($header, 9, 3); - $fetch_last_error = $header; + $key = strtolower($key); + + if ($key == 'content-type') { + $fetch_last_content_type = $value; + // don't abort here b/c there might be more than one + // e.g. if we were being redirected -- last one is the right one + } else if ($key == 'last-modified') { + $fetch_last_modified = $value; + } else if ($key == 'location') { + $fetch_effective_url = $value; } } + + if (substr(strtolower($header), 0, 7) == 'http/1.') { + $fetch_last_error_code = (int) substr($header, 9, 3); + $fetch_last_error = $header; + } } if ($fetch_last_error_code != 200) { @@ -483,7 +472,7 @@ class UrlHelper { $is_gzipped = RSSUtils::is_gzipped($data); - if ($is_gzipped) { + if ($is_gzipped && $data) { $tmp = @gzdecode($data); if ($tmp) $data = $tmp; diff --git a/classes/userhelper.php b/classes/userhelper.php index 76bb338d4..b0a9dc598 100644 --- a/classes/userhelper.php +++ b/classes/userhelper.php @@ -75,7 +75,7 @@ class UserHelper { if (!$pluginhost) $pluginhost = PluginHost::getInstance(); - if ($owner_uid && SCHEMA_VERSION >= 100 && !$_SESSION["safe_mode"]) { + if ($owner_uid && SCHEMA_VERSION >= 100 && empty($_SESSION["safe_mode"])) { $plugins = get_pref("_ENABLED_PLUGINS", $owner_uid); $pluginhost->load($plugins, PluginHost::KIND_USER, $owner_uid); @@ -97,7 +97,7 @@ class UserHelper { } else { if (!validate_session()) $_SESSION["uid"] = false; - if (!$_SESSION["uid"]) { + if (empty($_SESSION["uid"])) { if (AUTH_AUTO_LOGIN && self::authenticate(null, null)) { $_SESSION["ref_schema_version"] = get_schema_version(true); @@ -105,7 +105,7 @@ class UserHelper { self::authenticate(null, null, true); } - if (!$_SESSION["uid"]) { + if (empty($_SESSION["uid"])) { Pref_Users::logout_user(); Handler_Public::render_login_form(); |