summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2019-08-16 12:53:51 +0300
committerAndrew Dolgov <[email protected]>2019-08-16 12:53:51 +0300
commit88077702f3a517a0c5b3dbf52acc3f2f51bc6c62 (patch)
tree17da7c296a12ce21368ce260afdf9b7eb2a566c2
parent24f55d5b919d4b39664b245e51c1d7b984a9966c (diff)
parenta2d26867e653d34a80e504478ebe30ff69ef4a33 (diff)
Merge branch 'master' of git.fakecake.org:tt-rss
-rwxr-xr-xclasses/api.php8
-rw-r--r--classes/backend.php2
-rwxr-xr-xclasses/handler/public.php20
-rw-r--r--classes/pluginhandler.php5
-rwxr-xr-xclasses/pluginhost.php32
-rwxr-xr-xclasses/rpc.php2
-rw-r--r--include/functions.php2
-rw-r--r--plugins/af_proxy_http/init.php3
8 files changed, 54 insertions, 20 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/handler/public.php b/classes/handler/public.php
index 05a84494b..91413b976 100755
--- a/classes/handler/public.php
+++ b/classes/handler/public.php
@@ -1203,30 +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: Requested private method '$method' of plugin '$plugin'.");
+ 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: Requested unknown method '$method' of plugin '$plugin'.");
+ 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: Requested method '$method' of unknown plugin '$plugin'.");
+ 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/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 4d5b3252c..eab808ae9 100755
--- a/classes/pluginhost.php
+++ b/classes/pluginhost.php
@@ -186,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;
@@ -491,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/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/include/functions.php b/include/functions.php
index c326ac468..e78f0de9d 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -593,7 +593,7 @@
}
function clean_filename($filename) {
- return basename(preg_replace("/\.\.|[\/\\\]/", "", $filename));
+ return basename(preg_replace("/\.\.|[\/\\\]/", "", clean($filename)));
}
function make_password($length = 12) {
diff --git a/plugins/af_proxy_http/init.php b/plugins/af_proxy_http/init.php
index 421e04d1f..80100160d 100644
--- a/plugins/af_proxy_http/init.php
+++ b/plugins/af_proxy_http/init.php
@@ -141,8 +141,7 @@ class Af_Proxy_Http extends Plugin {
}
}
- return get_self_url_prefix() . "/public.php?op=pluginhandler&plugin=af_proxy_http&pmethod=imgproxy&url=" .
- urlencode($url);
+ return $this->host->get_public_method_url($this, "imgproxy", ["url" => $url]);
}
}
}