25 #include "model/plugin_blacklist.h"
30 #include <unordered_map>
33 #include <wx/translation.h>
36 #include "model/logger.h"
47 static const char SEP =
'\\';
49 static const char SEP =
'/';
62 static const char*
const STD_HARD_MSG = _(R
"(
63 PlugIn %s, version %i.%i was detected.
64 This version is known to be unstable and will not be loaded.
65 Please update this PlugIn using the PlugIn manager master catalog.
68 static const char*
const STD_SOFT_MSG = _(R
"(
69 PlugIn %s, version %i.%i was detected.
70 This version is known to be unstable.
71 Please update this PlugIn using the PlugIn manager master catalog.
74 static const char*
const OCHART_OBSOLETED_MSG = _(R
"(
75 PlugIn %s, version %i.%i was detected.
76 This plugin is obsolete, the o-charts plugin should be used
77 instead. Please uninstall this plugin and install o-charts
78 using the PlugIn manager master catalog.
83 {
"Radar", 0, 95,
true, STD_HARD_MSG},
84 {
"Watchdog", 1, 0,
true, STD_HARD_MSG},
85 {
"squiddio", 0, 2,
true, STD_HARD_MSG},
86 {
"ObjSearch", 0, 3,
true, STD_HARD_MSG},
88 {
"S63", 0, 6,
true, STD_HARD_MSG},
90 {
"oeSENC", 99, 99,
true, OCHART_OBSOLETED_MSG},
91 {
"oernc_pi", 99, 99,
true, OCHART_OBSOLETED_MSG},
92 {
"oesenc_pi", 99, 99,
true, OCHART_OBSOLETED_MSG}
104 : major(0), minor(0), status(plug_status::unblocked), message(
"") {};
106 block(
int _major,
int _minor)
107 : major(_major), minor(_minor), status(plug_status::unblocked),
113 status(cb.hard ? plug_status::hard : plug_status::soft),
119 if (major == -1)
return true;
120 if (_major == -1)
return false;
121 if (_major > major)
return false;
122 if (_minor > minor)
return false;
126 plug_data to_plug_data(std::string name) {
134 static inline std::string normalize_lib(
const std::string& name) {
136 auto slashpos = libname.rfind(SEP);
137 if (slashpos != std::string::npos) libname = libname.substr(slashpos + 1);
138 #if defined(__WXGTK__) || defined(__WXOSX__)
139 if (libname.find(
"lib") == 0) libname = libname.substr(3);
141 auto dotpos = libname.rfind(
'.');
142 if (dotpos != std::string::npos) libname = libname.substr(0, dotpos);
146 static std::string to_lower(
const std::string& arg) {
148 std::transform(s.begin(), s.end(), s.begin(),
149 [](
unsigned char c){ return std::tolower(c); });
156 friend std::unique_ptr<AbstractBlacklist> blacklist_factory();
158 typedef std::unordered_map<std::string, block> block_map;
162 constexpr
int list_len =
sizeof(plugin_blacklist)/
sizeof(
config_block);
163 for (
int i = 0; i < list_len; i += 1) {
164 m_blocks[plugin_blacklist[i].name] =
block(plugin_blacklist[i]);
170 block_map::iterator find_block(
const std::string& name) {
171 const auto s = to_lower(name);
172 for (
auto it = m_blocks.begin(); it != m_blocks.end(); it++) {
173 if (to_lower(it->first) == s)
return it;
175 return m_blocks.end();
178 bool update_block(
const std::string& name,
int major,
int minor) {
179 bool new_block =
false;
180 if (m_blocks.find(name) == m_blocks.end()) {
181 m_blocks[name] =
block(major, minor);
184 m_blocks[name].status = plug_status::unloadable;
185 m_blocks[name].major = major;
186 m_blocks[name].minor = minor;
191 std::string format_message(
const std::string msg,
const plug_data& data) {
192 int size = std::snprintf(
nullptr, 0, msg.c_str(),
193 data.name.c_str(), data.major, data.minor);
195 wxLogWarning(
"Cannot format message for %s", data.name.c_str());
196 return "Internal error: Cannot format message(!)";
198 std::unique_ptr<char[]> buf(
new char[size]);
199 std::snprintf(buf.get(), size, msg.c_str(),
200 data.name.c_str(), data.major, data.minor);
201 return std::string(buf.get(), buf.get() + size - 1);
207 std::string filename(normalize_lib(library_file));
208 auto found = find_block(filename);
209 if (found == m_blocks.end())
return plug_data(
"", -1, -1);
210 return plug_data(found->first, found->second.major, found->second.minor);
213 plug_status
get_status(
const std::string& name,
int major,
int minor) {
214 if (m_blocks.find(name) == m_blocks.end())
return plug_status::unblocked;
215 const auto& b = m_blocks[name];
216 return b.is_matching(major, minor) ? b.status : plug_status::unblocked;
220 return get_status(pd.name, pd.major, pd.minor);
224 int major,
int minor) {
225 return update_block(name, major, minor);
231 auto slashpos = filename.rfind(SEP);
232 if (slashpos != std::string::npos)
233 filename = filename.substr(slashpos + 1);
234 return update_block(filename, -1, -1);
239 auto slashpos = filename.rfind(SEP);
240 if (slashpos != std::string::npos) filename = filename.substr(slashpos + 1);
242 if (m_blocks.find(filename) == m_blocks.end())
return true;
243 return m_blocks[filename].status != plug_status::unloadable;
247 #pragma GCC diagnostic push
248 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
250 if (status == plug_status::unloadable) {
251 std::string msg(_(
"Plugin library %s can not be loaded"));
252 msg = std::regex_replace(msg, std::regex(
"%s"), data.name);
255 if (status == plug_status::unblocked) {
256 wxLogMessage(
"Attempt to get message for unblocked plugin %s",
258 return "No applicable message";
260 auto found = find_block(data.name);
261 if (found == m_blocks.end())
262 return format_message(
"No known message for %s version %d.%d", data);
264 return format_message(found->second.message, data);
266 #pragma GCC diagnostic pop
270 std::unique_ptr<AbstractBlacklist> blacklist_factory() {
271 return std::unique_ptr<AbstractBlacklist>(
new PlugBlacklist());
274 #ifdef BLACKLIST_TEST
281 int main(
int argc,
char** argv) {
283 const std::string name(argv[1]);
284 int major = atoi(argv[2]);
285 int minor = atoi(argv[3]);
286 auto blacklist = blacklist_factory();
287 blacklist->mark_unloadable(
"foo");
288 auto s = blacklist->get_status(name, major, minor);
290 case plug_status::unloadable: std::cout <<
"unloadable\n";
break;
291 case plug_status::unblocked: std::cout <<
"unblocked\n";
break;
292 case plug_status::hard: std::cout <<
"hard\n";
break;
293 case plug_status::soft: std::cout <<
"soft\n";
break;
295 auto lib = blacklist->plugin_by_libname(name);
296 std::cout <<
"found plugin: \"" << lib.name <<
"\" version: " << lib.major
297 <<
"." << 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.
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().