changeset 805:8025a24bb7c7

irccd: protect loading of plugins Check if the extension is viable to avoid calling plugin_loader::open function if not required. While here, also add a message on successful load.
author David Demelier <markand@malikania.fr>
date Wed, 14 Nov 2018 20:11:00 +0100
parents d55a64c6586b
children 75aca6bc1cd7
files libirccd-js/irccd/js/js_plugin.cpp libirccd-js/irccd/js/js_plugin.hpp libirccd/irccd/daemon/dynlib_plugin.cpp libirccd/irccd/daemon/plugin.cpp libirccd/irccd/daemon/plugin.hpp libirccd/irccd/daemon/plugin_service.cpp
diffstat 6 files changed, 43 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd-js/irccd/js/js_plugin.cpp	Wed Nov 14 14:07:05 2018 +0100
+++ b/libirccd-js/irccd/js/js_plugin.cpp	Wed Nov 14 20:11:00 2018 +0100
@@ -313,8 +313,10 @@
 	call("onWhois", event.server, event.whois);
 }
 
-js_plugin_loader::js_plugin_loader(irccd& irccd) noexcept
-	: plugin_loader({}, { ".js" })
+js_plugin_loader::js_plugin_loader(irccd& irccd,
+                                   std::vector<std::string> directories,
+                                   std::vector<std::string> extensions) noexcept
+	: plugin_loader(std::move(directories), std::move(extensions))
 	, irccd_(irccd)
 {
 }
@@ -333,9 +335,6 @@
 
 auto js_plugin_loader::open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>
 {
-	if (path.rfind(".js") == std::string::npos)
-		return nullptr;
-
 	auto plugin = std::make_shared<js_plugin>(std::string(id), std::string(path));
 
 	for (const auto& mod : modules_)
--- a/libirccd-js/irccd/js/js_plugin.hpp	Wed Nov 14 14:07:05 2018 +0100
+++ b/libirccd-js/irccd/js/js_plugin.hpp	Wed Nov 14 20:11:00 2018 +0100
@@ -259,8 +259,12 @@
 	 * Constructor.
 	 *
 	 * \param irccd the irccd instance
+	 * \param directories directories to search
+	 * \param extensions extensions to search
 	 */
-	js_plugin_loader(irccd& irccd) noexcept;
+	js_plugin_loader(irccd& irccd,
+	                 std::vector<std::string> directories = {},
+	                 std::vector<std::string> extensions = {".js"}) noexcept;
 
 	/**
 	 * Destructor defaulted.
--- a/libirccd/irccd/daemon/dynlib_plugin.cpp	Wed Nov 14 14:07:05 2018 +0100
+++ b/libirccd/irccd/daemon/dynlib_plugin.cpp	Wed Nov 14 20:11:00 2018 +0100
@@ -75,8 +75,6 @@
 
 	const auto [ abisym, initsym ] = symbol(pathstr);
 
-	printf("abisym: %s\n", abisym.c_str());
-	printf("initsym: %s\n", initsym.c_str());
 	using abisym_func_type = version ();
 	using initsym_func_type = std::unique_ptr<plugin> (std::string);
 
--- a/libirccd/irccd/daemon/plugin.cpp	Wed Nov 14 14:07:05 2018 +0100
+++ b/libirccd/irccd/daemon/plugin.cpp	Wed Nov 14 20:11:00 2018 +0100
@@ -163,7 +163,21 @@
 	: directories_(std::move(directories))
 	, extensions_(std::move(extensions))
 {
-	assert(!extensions_.empty());
+}
+
+auto plugin_loader::is_supported(std::string_view path) noexcept -> bool
+{
+	const std::string name(path);
+
+	for (const auto& ext : extensions_)
+		if (boost::filesystem::path(name).extension() == ext)
+			return true;
+
+	/*
+	 * If extensions are not specified, let plugin_loader::open a chance
+	 * to be called anyway.
+	 */
+	return extensions_.empty();
 }
 
 auto plugin_loader::find(std::string_view name) -> std::shared_ptr<plugin>
--- a/libirccd/irccd/daemon/plugin.hpp	Wed Nov 14 14:07:05 2018 +0100
+++ b/libirccd/irccd/daemon/plugin.hpp	Wed Nov 14 20:11:00 2018 +0100
@@ -337,14 +337,15 @@
 
 public:
 	/**
-	 * Construct the loader with a predefined set of directories and extensions.
+	 * Construct the loader with a predefined set of directories and
+	 * extensions.
 	 *
-	 * If directories is not specified, a sensible default list of system and
-	 * user paths are searched.
+	 * If directories is not specified, a sensible default list of system
+	 * and user paths are searched.
 	 *
 	 * \pre !extensions.empty()
 	 * \param directories optional list of directories to search
-	 * \param extensions the non empty list of extensions supported
+	 * \param extensions optional list of extensions
 	 */
 	plugin_loader(std::vector<std::string> directories,
 	              std::vector<std::string> extensions) noexcept;
@@ -355,6 +356,14 @@
 	virtual ~plugin_loader() = default;
 
 	/**
+	 * Tells if the plugin should be opened by checking file extension.
+	 *
+	 * \param path the path
+	 * \return true if the extension matches
+	 */
+	virtual auto is_supported(std::string_view path) noexcept -> bool;
+
+	/**
 	 * Try to open the plugin specified by path.
 	 *
 	 * The implementation must test if the plugin is suitable for opening, by
--- a/libirccd/irccd/daemon/plugin_service.cpp	Wed Nov 14 14:07:05 2018 +0100
+++ b/libirccd/irccd/daemon/plugin_service.cpp	Wed Nov 14 20:11:00 2018 +0100
@@ -148,6 +148,9 @@
 auto plugin_service::open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>
 {
 	for (const auto& loader : loaders_) {
+		if (!loader->is_supported(path))
+			continue;
+
 		auto plugin = loader->open(id, path);
 
 		if (plugin)
@@ -193,7 +196,9 @@
 	plugin->set_paths(get_paths(id));
 
 	exec(plugin, &plugin::handle_load, irccd_);
-	add(std::move(plugin));
+	add(plugin);
+
+	irccd_.get_log().info(*plugin) << "loaded version " << plugin->get_version() << std::endl;
 }
 
 void plugin_service::reload(std::string_view id)