From e4609c18efceebb1e021d814f53061ada7f6489a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 17 Feb 2021 21:44:21 +0300 Subject: [PATCH 1/2] * add (disabled) shortcut syntax for plugin methods * add controls shortcut for pluginhandler tags * add similar shortcut for frontend * allow plugins to selectively exclude their methods from CSRF checking --- backend.php | 11 +++++++++++ classes/plugin.php | 4 ++++ classes/pluginhandler.php | 2 +- classes/pluginhost.php | 13 ++++++++++++- include/controls.php | 12 +++++++++++- js/App.js | 3 +++ plugins/af_proxy_http/init.php | 4 +--- plugins/af_psql_trgm/init.php | 4 +--- plugins/af_readability/init.js | 2 +- plugins/af_readability/init.php | 6 ++---- plugins/af_redditimgur/init.php | 9 +++++---- plugins/mail/init.php | 12 ++++-------- plugins/mail/mail.js | 2 +- plugins/mailto/init.js | 2 +- plugins/note/init.php | 4 +--- plugins/note/note.js | 2 +- plugins/nsfw/init.php | 4 +--- plugins/share/share.js | 8 +++----- plugins/share/share_prefs.js | 2 +- 19 files changed, 65 insertions(+), 41 deletions(-) diff --git a/backend.php b/backend.php index 9ecc22914..e64c6561f 100644 --- a/backend.php +++ b/backend.php @@ -88,6 +88,17 @@ 5 => __("Power User"), 10 => __("Administrator")); + // shortcut syntax for plugin methods (?op=plugin--pmethod&...params) + /* if (strpos($op, PluginHost::PUBLIC_METHOD_DELIMITER) !== false) { + list ($plugin, $pmethod) = explode(PluginHost::PUBLIC_METHOD_DELIMITER, $op, 2); + + // TODO: better implementation that won't modify $_REQUEST + $_REQUEST["plugin"] = $plugin; + $method = $pmethod; + $op = "pluginhandler"; + } */ + + // TODO: figure out if is this still needed $op = str_replace("-", "_", $op); $override = PluginHost::getInstance()->lookup_handler($op, $method); diff --git a/classes/plugin.php b/classes/plugin.php index 2416418cd..6c572467a 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -54,4 +54,8 @@ abstract class Plugin { return vsprintf($this->__($msgid), $args); } + + function csrf_ignore($method) { + return false; + } } diff --git a/classes/pluginhandler.php b/classes/pluginhandler.php index a0e60b4e6..608f80dcb 100644 --- a/classes/pluginhandler.php +++ b/classes/pluginhandler.php @@ -11,7 +11,7 @@ class PluginHandler extends Handler_Protected { if ($plugin) { if (method_exists($plugin, $method)) { - if (validate_csrf($csrf_token)) { + if (validate_csrf($csrf_token) || $plugin->csrf_ignore($method)) { $plugin->$method(); } else { user_error("Rejected ${plugin_name}->${method}(): invalid CSRF token.", E_USER_WARNING); diff --git a/classes/pluginhost.php b/classes/pluginhost.php index 097bf987c..065fa99c4 100755 --- a/classes/pluginhost.php +++ b/classes/pluginhost.php @@ -611,6 +611,17 @@ class PluginHost { $params)); } + // shortcut syntax (disabled for now) + /* function get_method_url(Plugin $sender, string $method, $params) { + return get_self_url_prefix() . "/backend.php?" . + http_build_query( + array_merge( + [ + "op" => strtolower(get_class($sender) . self::PUBLIC_METHOD_DELIMITER . $method), + ], + $params)); + } */ + // WARNING: endpoint in public.php, exposed to unauthenticated users function get_public_method_url(Plugin $sender, string $method, $params) { if ($sender->is_public_method($method)) { @@ -618,7 +629,7 @@ class PluginHost { http_build_query( array_merge( [ - "op" => strtolower(get_class($sender) . PluginHost::PUBLIC_METHOD_DELIMITER . $method), + "op" => strtolower(get_class($sender) . self::PUBLIC_METHOD_DELIMITER . $method), ], $params)); } else { diff --git a/include/controls.php b/include/controls.php index 4c60d94f3..d8506877b 100755 --- a/include/controls.php +++ b/include/controls.php @@ -11,6 +11,17 @@ return $rv; } + // shortcut syntax (disabled) + /* function pluginhandler_tags(\Plugin $plugin, string $method) { + return hidden_tag("op", strtolower(get_class($plugin) . \PluginHost::PUBLIC_METHOD_DELIMITER . $method)); + } */ + + function pluginhandler_tags(\Plugin $plugin, string $method) { + return hidden_tag("op", "pluginhandler") . + hidden_tag("plugin", strtolower(get_class($plugin))) . + hidden_tag("method", $method); + } + function button_tag(string $value, string $type, array $attributes = []) { return ""; } @@ -155,4 +166,3 @@ return $ret; } - diff --git a/js/App.js b/js/App.js index 9d8f6c275..aeca688b7 100644 --- a/js/App.js +++ b/js/App.js @@ -101,6 +101,9 @@ const App = { return dijit.getEnclosingWidget(elem.closest('.dijitDialog')); }, + getPhArgs(plugin, method, args = {}) { + return {...{op: "pluginhandler", plugin: plugin, method: method}, ...args}; + }, label_to_feed_id: function(label) { return this.LABEL_BASE_INDEX - 1 - Math.abs(label); }, diff --git a/plugins/af_proxy_http/init.php b/plugins/af_proxy_http/init.php index 5804e450f..d6cee5fcd 100644 --- a/plugins/af_proxy_http/init.php +++ b/plugins/af_proxy_http/init.php @@ -229,9 +229,7 @@ class Af_Proxy_Http extends Plugin { } "; - print \Controls\hidden_tag("op", "pluginhandler"); - print \Controls\hidden_tag("method", "save"); - print \Controls\hidden_tag("plugin", "af_proxy_http"); + print \Controls\pluginhandler_tags($this, "save"); $proxy_all = sql_bool_to_bool($this->host->get($this, "proxy_all")); print \Controls\checkbox_tag("proxy_all", $proxy_all); diff --git a/plugins/af_psql_trgm/init.php b/plugins/af_psql_trgm/init.php index 1d83ce5e0..bfbbdf49c 100644 --- a/plugins/af_psql_trgm/init.php +++ b/plugins/af_psql_trgm/init.php @@ -157,9 +157,7 @@ class Af_Psql_Trgm extends Plugin { } "; - print \Controls\hidden_tag("op", "pluginhandler"); - print \Controls\hidden_tag("method", "save"); - print \Controls\hidden_tag("plugin", "af_psql_trgm"); + print \Controls\pluginhandler_tags($this, "save"); print "

" . __("Global settings") . "

"; diff --git a/plugins/af_readability/init.js b/plugins/af_readability/init.js index 3155475cc..ff2d94e8b 100644 --- a/plugins/af_readability/init.js +++ b/plugins/af_readability/init.js @@ -16,7 +16,7 @@ Plugins.Af_Readability = { Notify.progress("Loading, please wait..."); - xhrJson("backend.php",{ op: "pluginhandler", plugin: "af_readability", method: "embed", param: id }, (reply) => { + xhrJson("backend.php", App.getPhArgs("af_readability", "embed", {id: id}), (reply) => { if (content && reply.content) { content.setAttribute(self.orig_attr_name, content.innerHTML); diff --git a/plugins/af_readability/init.php b/plugins/af_readability/init.php index aeef8cddc..43d064fc7 100755 --- a/plugins/af_readability/init.php +++ b/plugins/af_readability/init.php @@ -67,9 +67,7 @@ class Af_Readability extends Plugin {
- - - +