25#include "model/plugin_blacklist.h"
30#include <unordered_map>
33#include <wx/translation.h>
45static const char SEP =
'\\';
47static const char SEP =
'/';
60static const char*
const STD_HARD_MSG = _(R
"(
61PlugIn %s, version %i.%i was detected.
62This version is known to be unstable and will not be loaded.
63Please update this PlugIn using the PlugIn manager master catalog.
66static const char*
const STD_SOFT_MSG = _(R
"(
67PlugIn %s, version %i.%i was detected.
68This version is known to be unstable.
69Please update this PlugIn using the PlugIn manager master catalog.
72static const char*
const OCHART_OBSOLETED_MSG = _(R
"(
73PlugIn %s, version %i.%i was detected.
74This plugin is obsolete, the o-charts plugin should be used
75instead. Please uninstall this plugin and install o-charts
76using the PlugIn manager master catalog.
80 {
"Radar", 0, 95,
true, STD_HARD_MSG},
81 {
"Watchdog", 1, 0,
true, STD_HARD_MSG},
82 {
"squiddio", 0, 2,
true, STD_HARD_MSG},
83 {
"ObjSearch", 0, 3,
true, STD_HARD_MSG},
85 {
"S63", 0, 6,
true, STD_HARD_MSG},
87 {
"oeSENC", 99, 99,
true, OCHART_OBSOLETED_MSG},
88 {
"oernc_pi", 99, 99,
true, OCHART_OBSOLETED_MSG},
89 {
"oesenc_pi", 99, 99,
true, OCHART_OBSOLETED_MSG}};
98 block() : major(0), minor(0), status(plug_status::unblocked), message(
"") {};
100 block(
int _major,
int _minor)
103 status(plug_status::unblocked),
108 minor(cb.version_minor),
109 status(cb.hard ? plug_status::hard : plug_status::soft),
114 if (major == -1)
return true;
115 if (_major == -1)
return false;
116 if (_major > major)
return false;
117 if (_minor > minor)
return false;
121 plug_data to_plug_data(std::string name) {
128static inline std::string normalize_lib(
const std::string& name) {
130 auto slashpos = libname.rfind(SEP);
131 if (slashpos != std::string::npos) libname = libname.substr(slashpos + 1);
132#if defined(__WXGTK__) || defined(__WXOSX__)
133 if (libname.find(
"lib") == 0) libname = libname.substr(3);
135 auto dotpos = libname.rfind(
'.');
136 if (dotpos != std::string::npos) libname = libname.substr(0, dotpos);
140static std::string to_lower(
const std::string& arg) {
142 std::transform(s.begin(), s.end(), s.begin(),
143 [](
unsigned char c) { return std::tolower(c); });
148 friend std::unique_ptr<AbstractBlacklist> blacklist_factory();
150 typedef std::unordered_map<std::string, block> block_map;
154 constexpr int list_len =
sizeof(plugin_blacklist) /
sizeof(
config_block);
155 for (
int i = 0; i < list_len; i += 1) {
156 m_blocks[plugin_blacklist[i].name] =
block(plugin_blacklist[i]);
162 block_map::iterator find_block(
const std::string& name) {
163 const auto s = to_lower(name);
164 for (
auto it = m_blocks.begin(); it != m_blocks.end(); it++) {
165 if (to_lower(it->first) == s)
return it;
167 return m_blocks.end();
170 bool update_block(
const std::string& name,
int major,
int minor) {
171 bool new_block =
false;
172 if (m_blocks.find(name) == m_blocks.end()) {
173 m_blocks[name] =
block(major, minor);
176 m_blocks[name].status = plug_status::unloadable;
177 m_blocks[name].major = major;
178 m_blocks[name].minor = minor;
183 std::string format_message(
const std::string msg,
const plug_data& data) {
184 int size = std::snprintf(
nullptr, 0, msg.c_str(), data.name.c_str(),
185 data.major, data.minor);
187 wxLogWarning(
"Cannot format message for %s", data.name.c_str());
188 return "Internal error: Cannot format message(!)";
190 std::unique_ptr<char[]> buf(
new char[size]);
191 std::snprintf(buf.get(), size, msg.c_str(), data.name.c_str(), data.major,
193 return std::string(buf.get(), buf.get() + size - 1);
198 std::string filename(normalize_lib(library_file));
199 auto found = find_block(filename);
200 if (found == m_blocks.end())
return plug_data(
"", -1, -1);
201 return plug_data(found->first, found->second.major, found->second.minor);
204 plug_status
get_status(
const std::string& name,
int major,
int minor) {
205 if (m_blocks.find(name) == m_blocks.end())
return plug_status::unblocked;
206 const auto& b = m_blocks[name];
207 return b.is_matching(major, minor) ? b.status : plug_status::unblocked;
211 return get_status(pd.name, pd.major, pd.minor);
215 return update_block(name, major, minor);
221 auto slashpos = filename.rfind(SEP);
222 if (slashpos != std::string::npos) filename = filename.substr(slashpos + 1);
223 return update_block(filename, -1, -1);
228 auto slashpos = filename.rfind(SEP);
229 if (slashpos != std::string::npos) filename = filename.substr(slashpos + 1);
231 if (m_blocks.find(filename) == m_blocks.end())
return true;
232 return m_blocks[filename].status != plug_status::unloadable;
236#pragma GCC diagnostic push
237#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
239 if (status == plug_status::unloadable) {
240 std::string msg(_(
"Plugin library %s can not be loaded"));
241 msg = std::regex_replace(msg, std::regex(
"%s"), data.name);
244 if (status == plug_status::unblocked) {
245 wxLogMessage(
"Attempt to get message for unblocked plugin %s",
247 return "No applicable message";
249 auto found = find_block(data.name);
250 if (found == m_blocks.end())
251 return format_message(
"No known message for %s version %d.%d", data);
253 return format_message(found->second.message, data);
255#pragma GCC diagnostic pop
258std::unique_ptr<AbstractBlacklist> blacklist_factory() {
259 return std::unique_ptr<AbstractBlacklist>(
new PlugBlacklist());
269int main(
int argc,
char** argv) {
270 const std::string name(argv[1]);
271 int major = atoi(argv[2]);
272 int minor = atoi(argv[3]);
273 auto blacklist = blacklist_factory();
274 blacklist->mark_unloadable(
"foo");
275 auto s = blacklist->get_status(name, major, minor);
277 case plug_status::unloadable:
278 std::cout <<
"unloadable\n";
280 case plug_status::unblocked:
281 std::cout <<
"unblocked\n";
283 case plug_status::hard:
284 std::cout <<
"hard\n";
286 case plug_status::soft:
287 std::cout <<
"soft\n";
290 auto lib = blacklist->plugin_by_libname(name);
291 std::cout <<
"found plugin: \"" << lib.name <<
"\" version: " << lib.major
292 <<
"." << lib.minor <<
"\n";
Plugins could be blacklisted in runtime if they are unloadable or in hardcoded, compile-time list.
plug_status get_status(const plug_data pd)
Return status for given official plugin name and version.
bool mark_unloadable(const std::string &path)
Given a path, mark filename as unloadable.
virtual plug_data get_library_data(const std::string &library_file)
Best effort attempt to get data for a library file.
bool is_loadable(const std::string path)
Return true iff plugin (a path) is loadable.
virtual bool mark_unloadable(const std::string &name, int major, int minor)
Given plugin name and version mark it as unloadable.
std::string get_message(plug_status status, const plug_data &data)
Return plugin-specific message, possibly "".
plug_status get_status(const std::string &name, int major, int minor)
Return status for given official plugin name and version.
Enhanced logging interface on top of wx/log.h.
Runtime representation of a plugin block.
bool is_matching(int _major, int _minor) const
Return true if _major/_minor matches the blocked plugin.
Hardcoded representation of a blocked plugin.
const char * message
If true, unconditional hard block; else load plugin with a warning.
int version_major
Official plugin name as of GetCommonName().