summaryrefslogtreecommitdiff
path: root/classes
diff options
context:
space:
mode:
Diffstat (limited to 'classes')
-rwxr-xr-xclasses/api.php8
-rw-r--r--classes/backend.php2
-rwxr-xr-xclasses/feeds.php19
-rwxr-xr-xclasses/handler/public.php19
-rwxr-xr-xclasses/logger/sql.php11
-rw-r--r--classes/pluginhandler.php5
-rwxr-xr-xclasses/pluginhost.php64
-rwxr-xr-xclasses/pref/feeds.php2
-rwxr-xr-xclasses/rpc.php2
-rwxr-xr-xclasses/rssutils.php18
10 files changed, 113 insertions, 37 deletions
diff --git a/classes/api.php b/classes/api.php
index 44c9841ce..01ea1970d 100755
--- a/classes/api.php
+++ b/classes/api.php
@@ -535,6 +535,7 @@ class API extends Handler {
/* Labels */
+ /* API only: -4 All feeds, including virtual feeds */
if ($cat_id == -4 || $cat_id == -2) {
$counters = Counters::getLabelCounters(true);
@@ -582,7 +583,7 @@ class API extends Handler {
if ($include_nested && $cat_id) {
$sth = $pdo->prepare("SELECT
id, title, order_id FROM ttrss_feed_categories
- WHERE parent_cat = ? AND owner_uid = ? ORDER BY id, title");
+ WHERE parent_cat = ? AND owner_uid = ? ORDER BY order_id, title");
$sth->execute([$cat_id, $_SESSION['uid']]);
@@ -611,12 +612,13 @@ class API extends Handler {
$limit_qpart = "";
}
+ /* API only: -3 All feeds, excluding virtual feeds (e.g. Labels and such) */
if ($cat_id == -4 || $cat_id == -3) {
$sth = $pdo->prepare("SELECT
id, feed_url, cat_id, title, order_id, ".
SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE owner_uid = ?
- ORDER BY cat_id, title " . $limit_qpart);
+ ORDER BY order_id, title " . $limit_qpart);
$sth->execute([$_SESSION['uid']]);
} else {
@@ -627,7 +629,7 @@ class API extends Handler {
FROM ttrss_feeds WHERE
(cat_id = :cat OR (:cat = 0 AND cat_id IS NULL))
AND owner_uid = :uid
- ORDER BY cat_id, title " . $limit_qpart);
+ ORDER BY order_id, title " . $limit_qpart);
$sth->execute([":uid" => $_SESSION['uid'], ":cat" => $cat_id]);
}
diff --git a/classes/backend.php b/classes/backend.php
index 5bd724728..122e28c65 100644
--- a/classes/backend.php
+++ b/classes/backend.php
@@ -88,7 +88,7 @@ class Backend extends Handler {
}
function help() {
- $topic = basename(clean($_REQUEST["topic"])); // only one for now
+ $topic = clean_filename($_REQUEST["topic"]); // only one for now
if ($topic == "main") {
$info = get_hotkeys_info();
diff --git a/classes/feeds.php b/classes/feeds.php
index b89f4e4ca..bae571a3f 100755
--- a/classes/feeds.php
+++ b/classes/feeds.php
@@ -2,6 +2,8 @@
require_once "colors.php";
class Feeds extends Handler_Protected {
+ const NEVER_GROUP_FEEDS = [ -6, 0 ];
+ const NEVER_GROUP_BY_DATE = [ -2, -1, -3 ];
private $params;
@@ -199,7 +201,8 @@ class Feeds extends Handler_Protected {
$qfh_ret = $this->queryFeedHeadlines($params);
}
- $vfeed_group_enabled = get_pref("VFEED_GROUP_BY_FEED") && $feed != -6;
+ $vfeed_group_enabled = get_pref("VFEED_GROUP_BY_FEED") &&
+ !(in_array($feed, Feeds::NEVER_GROUP_FEEDS) && !$cat_view);
$result = $qfh_ret[0]; // this could be either a PDO query result or a -1 if first id changed
$feed_title = $qfh_ret[1];
@@ -1438,7 +1441,7 @@ class Feeds extends Handler_Protected {
$start_ts = isset($params["start_ts"]) ? $params["start_ts"] : false;
$check_first_id = isset($params["check_first_id"]) ? $params["check_first_id"] : false;
$skip_first_id_check = isset($params["skip_first_id_check"]) ? $params["skip_first_id_check"] : false;
- $order_by = isset($params["order_by"]) ? $params["order_by"] : false;
+ //$order_by = isset($params["order_by"]) ? $params["order_by"] : false;
$ext_tables_part = "";
$limit_query_part = "";
@@ -1693,12 +1696,18 @@ class Feeds extends Handler_Protected {
if (is_numeric($feed)) {
// proper override_order applied above
if ($vfeed_query_part && !$ignore_vfeed_group && get_pref('VFEED_GROUP_BY_FEED', $owner_uid)) {
- $yyiw_desc = $order_by == "date_reverse" ? "" : "desc";
+
+ if (!(in_array($feed, Feeds::NEVER_GROUP_BY_DATE) && !$cat_view)) {
+ $yyiw_desc = $order_by == "date_reverse" ? "" : "desc";
+ $yyiw_order_qpart = "yyiw $yyiw_desc, ";
+ } else {
+ $yyiw_order_qpart = "";
+ }
if (!$override_order) {
- $order_by = "yyiw $yyiw_desc, ttrss_feeds.title, ".$order_by;
+ $order_by = "$yyiw_order_qpart ttrss_feeds.title, $order_by";
} else {
- $order_by = "yyiw $yyiw_desc, ttrss_feeds.title, ".$override_order;
+ $order_by = "$yyiw_order_qpart ttrss_feeds.title, $override_order";
}
}
diff --git a/classes/handler/public.php b/classes/handler/public.php
index 06c01df57..e2082ff1e 100755
--- a/classes/handler/public.php
+++ b/classes/handler/public.php
@@ -509,7 +509,7 @@ class Handler_Public extends Handler {
<!DOCTYPE html>
<html>
<head>
- <title><?php echo __("Share with Tiny Tiny RSS") ?> ?></title>
+ <title><?php echo __("Share with Tiny Tiny RSS") ?></title>
<?php
echo stylesheet_tag("css/default.css");
echo javascript_tag("lib/prototype.js");
@@ -1203,27 +1203,30 @@ class Handler_Public extends Handler {
public function pluginhandler() {
$host = new PluginHost();
- $plugin = basename(clean($_REQUEST["plugin"]));
+ $plugin_name = clean_filename($_REQUEST["plugin"]);
$method = clean($_REQUEST["pmethod"]);
- $host->load($plugin, PluginHost::KIND_USER, 0);
+ $host->load($plugin_name, PluginHost::KIND_USER, 0);
$host->load_data();
- $pclass = $host->get_plugin($plugin);
+ $plugin = $host->get_plugin($plugin_name);
- if ($pclass) {
- if (method_exists($pclass, $method)) {
- if ($pclass->is_public_method($method)) {
- $pclass->$method();
+ if ($plugin) {
+ if (method_exists($plugin, $method)) {
+ if ($plugin->is_public_method($method)) {
+ $plugin->$method();
} else {
+ user_error("PluginHandler[PUBLIC]: Requested private method '$method' of plugin '$plugin_name'.", E_USER_WARNING);
header("Content-Type: text/json");
print error_json(6);
}
} else {
+ user_error("PluginHandler[PUBLIC]: Requested unknown method '$method' of plugin '$plugin_name'.", E_USER_WARNING);
header("Content-Type: text/json");
print error_json(13);
}
} else {
+ user_error("PluginHandler[PUBLIC]: Requested method '$method' of unknown plugin '$plugin_name'.", E_USER_WARNING);
header("Content-Type: text/json");
print error_json(14);
}
diff --git a/classes/logger/sql.php b/classes/logger/sql.php
index 989539e5d..1b44b1e5f 100755
--- a/classes/logger/sql.php
+++ b/classes/logger/sql.php
@@ -15,6 +15,17 @@ class Logger_SQL {
// limit context length, DOMDocument dumps entire XML in here sometimes, which may be huge
$context = mb_substr($context, 0, 8192);
+ $server_params = [
+ "IP" => "REMOTE_ADDR",
+ "Request URI" => "REQUEST_URI",
+ "User agent" => "HTTP_USER_AGENT",
+ ];
+
+ foreach ($server_params as $n => $p) {
+ if (isset($_SERVER[$p]))
+ $context .= "\n$n: " . $_SERVER[$p];
+ }
+
// passed error message may contain invalid unicode characters, failing to insert an error here
// would break the execution entirely by generating an actual fatal error instead of a E_WARNING etc
$errstr = UConverter::transcode($errstr, 'UTF-8', 'UTF-8');
diff --git a/classes/pluginhandler.php b/classes/pluginhandler.php
index d10343e09..9682e440f 100644
--- a/classes/pluginhandler.php
+++ b/classes/pluginhandler.php
@@ -5,15 +5,18 @@ class PluginHandler extends Handler_Protected {
}
function catchall($method) {
- $plugin = PluginHost::getInstance()->get_plugin(clean($_REQUEST["plugin"]));
+ $plugin_name = clean($_REQUEST["plugin"]);
+ $plugin = PluginHost::getInstance()->get_plugin($plugin_name);
if ($plugin) {
if (method_exists($plugin, $method)) {
$plugin->$method();
} else {
+ user_error("PluginHandler: Requested unknown method '$method' of plugin '$plugin_name'.", E_USER_WARNING);
print error_json(13);
}
} else {
+ user_error("PluginHandler: Requested method '$method' of unknown plugin '$plugin_name'.", E_USER_WARNING);
print error_json(14);
}
}
diff --git a/classes/pluginhost.php b/classes/pluginhost.php
index d09ecca17..eab808ae9 100755
--- a/classes/pluginhost.php
+++ b/classes/pluginhost.php
@@ -128,28 +128,44 @@ class PluginHost {
}
}
- function add_hook($type, $sender) {
+ function add_hook($type, $sender, $priority = 50) {
+ $priority = (int) $priority;
+
if (!is_array($this->hooks[$type])) {
- $this->hooks[$type] = array();
+ $this->hooks[$type] = [];
+ }
+
+ if (!is_array($this->hooks[$type][$priority])) {
+ $this->hooks[$type][$priority] = [];
}
- array_push($this->hooks[$type], $sender);
+ array_push($this->hooks[$type][$priority], $sender);
+ ksort($this->hooks[$type]);
}
function del_hook($type, $sender) {
if (is_array($this->hooks[$type])) {
- $key = array_Search($sender, $this->hooks[$type]);
- if ($key !== FALSE) {
- unset($this->hooks[$type][$key]);
+ foreach (array_keys($this->hooks[$type]) as $prio) {
+ $key = array_search($sender, $this->hooks[$type][$prio]);
+
+ if ($key !== FALSE) {
+ unset($this->hooks[$type][$prio][$key]);
+ }
}
}
}
function get_hooks($type) {
if (isset($this->hooks[$type])) {
- return $this->hooks[$type];
+ $tmp = [];
+
+ foreach (array_keys($this->hooks[$type]) as $prio) {
+ $tmp = array_merge($tmp, $this->hooks[$type][$prio]);
+ }
+
+ return $tmp;
} else {
- return array();
+ return [];
}
}
function load_all($kind, $owner_uid = false, $skip_init = false) {
@@ -170,7 +186,7 @@ class PluginHost {
foreach ($plugins as $class) {
$class = trim($class);
- $class_file = strtolower(basename($class));
+ $class_file = strtolower(clean_filename($class));
if (!is_dir(__DIR__."/../plugins/$class_file") &&
!is_dir(__DIR__."/../plugins.local/$class_file")) continue;
@@ -475,4 +491,34 @@ class PluginHost {
function get_owner_uid() {
return $this->owner_uid;
}
+
+ // handled by classes/pluginhandler.php, requires valid session
+ function get_method_url($sender, $method, $params) {
+ return get_self_url_prefix() . "/backend.php?" .
+ http_build_query(
+ array_merge(
+ [
+ "op" => "pluginhandler",
+ "plugin" => strtolower(get_class($sender)),
+ "method" => $method
+ ],
+ $params));
+ }
+
+ // WARNING: endpoint in public.php, exposed to unauthenticated users
+ function get_public_method_url($sender, $method, $params) {
+ if ($sender->is_public_method($method)) {
+ return get_self_url_prefix() . "/public.php?" .
+ http_build_query(
+ array_merge(
+ [
+ "op" => "pluginhandler",
+ "plugin" => strtolower(get_class($sender)),
+ "pmethod" => $method
+ ],
+ $params));
+ } else {
+ user_error("get_public_method_url: requested method '$method' of '" . get_class($sender) . "' is private.");
+ }
+ }
}
diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php
index c55affd77..f672a0375 100755
--- a/classes/pref/feeds.php
+++ b/classes/pref/feeds.php
@@ -312,7 +312,7 @@ class Pref_Feeds extends Handler_Protected {
array_push($root['items'], $feed);
}
- $root['param'] = vsprintf(_ngettext('(%d feed)', '(%d feeds)', count($cat['items'])), count($cat['items']));
+ $root['param'] = vsprintf(_ngettext('(%d feed)', '(%d feeds)', count($root['items'])), count($root['items']));
}
$fl = array();
diff --git a/classes/rpc.php b/classes/rpc.php
index 8736cbb65..84c9cfe92 100755
--- a/classes/rpc.php
+++ b/classes/rpc.php
@@ -572,7 +572,7 @@ class RPC extends Handler_Protected {
function log() {
$msg = clean($_REQUEST['msg']);
- $file = basename(clean($_REQUEST['file']));
+ $file = clean_filename($_REQUEST['file']);
$line = (int) clean($_REQUEST['line']);
$context = clean($_REQUEST['context']);
diff --git a/classes/rssutils.php b/classes/rssutils.php
index fe4c0a8a3..cee8be8ff 100755
--- a/classes/rssutils.php
+++ b/classes/rssutils.php
@@ -563,14 +563,6 @@ class RSSUtils {
Debug::log("orig date: " . $item->get_date(), Debug::$LOG_VERBOSE);
- if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
- $entry_timestamp = time();
- }
-
- $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
-
- Debug::log("date $entry_timestamp [$entry_timestamp_fmt]", Debug::$LOG_VERBOSE);
-
$entry_title = strip_tags($item->get_title());
$entry_link = rewrite_relative_url($site_url, clean($item->get_link()));
@@ -656,6 +648,7 @@ class RSSUtils {
"force_catchup" => false, // ugly hack for the time being
"score_modifier" => 0, // no previous value, plugin should recalculate score modifier based on content if needed
"language" => $entry_language,
+ "timestamp" => $entry_timestamp,
"num_comments" => $num_comments, // read only
"feed" => array("id" => $feed,
"fetch_url" => $fetch_url,
@@ -797,6 +790,15 @@ class RSSUtils {
$article_labels = $article["labels"];
$entry_score_modifier = (int) $article["score_modifier"];
$entry_language = $article["language"];
+ $entry_timestamp = $article["timestamp"];
+
+ if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
+ $entry_timestamp = time();
+ }
+
+ $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
+
+ Debug::log("date $entry_timestamp [$entry_timestamp_fmt]", Debug::$LOG_VERBOSE);
if (Debug::get_loglevel() >= Debug::$LOG_EXTENDED) {
Debug::log("article labels:", Debug::$LOG_VERBOSE);