28#include <unordered_map>
31#include <wx/translation.h>
44static const char SEP =
'\\';
46static const char SEP =
'/';
59static const char*
const STD_HARD_MSG = _(R
"(
60PlugIn %s, version %i.%i was detected.
61This version is known to be unstable and will not be loaded.
62Please update this PlugIn using the PlugIn manager master catalog.
65static const char*
const STD_SOFT_MSG = _(R
"(
66PlugIn %s, version %i.%i was detected.
67This version is known to be unstable.
68Please update this PlugIn using the PlugIn manager master catalog.
71static const char*
const OCHART_OBSOLETED_MSG = _(R
"(
72PlugIn %s, version %i.%i was detected.
73This plugin is obsolete, the o-charts plugin should be used
74instead. Please uninstall this plugin and install o-charts
75using the PlugIn manager master catalog.
79 {
"Radar", 0, 95,
true, STD_HARD_MSG},
80 {
"Watchdog", 1, 0,
true, STD_HARD_MSG},
81 {
"squiddio", 0, 2,
true, STD_HARD_MSG},
82 {
"ObjSearch", 0, 3,
true, STD_HARD_MSG},
84 {
"S63", 0, 6,
true, STD_HARD_MSG},
86 {
"oeSENC", 99, 99,
true, OCHART_OBSOLETED_MSG},
87 {
"oernc_pi", 99, 99,
true, OCHART_OBSOLETED_MSG},
88 {
"oesenc_pi", 99, 99,
true, OCHART_OBSOLETED_MSG}};
97 block() : major(0), minor(0), status(plug_status::unblocked), message(
"") {};
99 block(
int _major,
int _minor)
102 status(plug_status::unblocked),
107 minor(cb.version_minor),
108 status(cb.hard ? plug_status::hard : plug_status::soft),
113 if (major == -1)
return true;
114 if (_major == -1)
return false;
115 if (_major > major)
return false;
116 if (_minor > minor)
return false;
120 plug_data to_plug_data(std::string name) {
127static inline std::string normalize_lib(
const std::string& name) {
129 auto slashpos = libname.rfind(SEP);
130 if (slashpos != std::string::npos) libname = libname.substr(slashpos + 1);
131#if defined(__WXGTK__) || defined(__WXOSX__)
132 if (libname.find(
"lib") == 0) libname = libname.substr(3);
134 auto dotpos = libname.rfind(
'.');
135 if (dotpos != std::string::npos) libname = libname.substr(0, dotpos);
139static std::string to_lower(
const std::string& arg) {
141 std::transform(s.begin(), s.end(), s.begin(),
142 [](
unsigned char c) { return std::tolower(c); });
147 friend std::unique_ptr<AbstractBlacklist> blacklist_factory();
149 typedef std::unordered_map<std::string, block> block_map;
153 constexpr int list_len =
sizeof(plugin_blacklist) /
sizeof(
config_block);
154 for (
int i = 0; i < list_len; i += 1) {
155 m_blocks[plugin_blacklist[i].name] =
block(plugin_blacklist[i]);
161 block_map::iterator find_block(
const std::string& name) {
162 const auto s = to_lower(name);
163 for (
auto it = m_blocks.begin(); it != m_blocks.end(); it++) {
164 if (to_lower(it->first) == s)
return it;
166 return m_blocks.end();
169 bool update_block(
const std::string& name,
int major,
int minor) {
170 bool new_block =
false;
171 if (m_blocks.find(name) == m_blocks.end()) {
172 m_blocks[name] =
block(major, minor);
175 m_blocks[name].status = plug_status::unloadable;
176 m_blocks[name].major = major;
177 m_blocks[name].minor = minor;
182 std::string format_message(
const std::string msg,
const plug_data& data) {
183 int size = std::snprintf(
nullptr, 0, msg.c_str(), data.name.c_str(),
184 data.major, data.minor);
186 wxLogWarning(
"Cannot format message for %s", data.name.c_str());
187 return "Internal error: Cannot format message(!)";
189 std::unique_ptr<char[]> buf(
new char[size]);
190 std::snprintf(buf.get(), size, msg.c_str(), data.name.c_str(), data.major,
192 return std::string(buf.get(), buf.get() + size - 1);
197 std::string filename(normalize_lib(library_file));
198 auto found = find_block(filename);
199 if (found == m_blocks.end())
return plug_data(
"", -1, -1);
200 return plug_data(found->first, found->second.major, found->second.minor);
204 if (m_blocks.find(name) == m_blocks.end())
return plug_status::unblocked;
205 const auto& b = m_blocks[name];
206 return b.is_matching(major, minor) ? b.status : plug_status::unblocked;
210 return get_status(pd.name, pd.major, pd.minor);
214 return update_block(name, major, minor);
220 auto slashpos = filename.rfind(SEP);
221 if (slashpos != std::string::npos) filename = filename.substr(slashpos + 1);
222 return update_block(filename, -1, -1);
227 auto slashpos = filename.rfind(SEP);
228 if (slashpos != std::string::npos) filename = filename.substr(slashpos + 1);
230 if (m_blocks.find(filename) == m_blocks.end())
return true;
231 return m_blocks[filename].status != plug_status::unloadable;
235#pragma GCC diagnostic push
236#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
238 if (status == plug_status::unloadable) {
239 std::string msg(_(
"Plugin library %s can not be loaded"));
240 msg = std::regex_replace(msg, std::regex(
"%s"), data.name);
243 if (status == plug_status::unblocked) {
244 wxLogMessage(
"Attempt to get message for unblocked plugin %s",
246 return "No applicable message";
248 auto found = find_block(data.name);
249 if (found == m_blocks.end())
250 return format_message(
"No known message for %s version %d.%d", data);
252 return format_message(found->second.message, data);
254#pragma GCC diagnostic pop
257std::unique_ptr<AbstractBlacklist> blacklist_factory() {
258 return std::unique_ptr<AbstractBlacklist>(
new PlugBlacklist());
268int main(
int argc,
char** argv) {
269 const std::string name(argv[1]);
270 int major = atoi(argv[2]);
271 int minor = atoi(argv[3]);
272 auto blacklist = blacklist_factory();
273 blacklist->mark_unloadable(
"foo");
274 auto s = blacklist->get_status(name, major, minor);
276 case plug_status::unloadable:
277 std::cout <<
"unloadable\n";
279 case plug_status::unblocked:
280 std::cout <<
"unblocked\n";
282 case plug_status::hard:
283 std::cout <<
"hard\n";
285 case plug_status::soft:
286 std::cout <<
"soft\n";
289 auto lib = blacklist->plugin_by_libname(name);
290 std::cout <<
"found plugin: \"" << lib.name <<
"\" version: " << lib.major
291 <<
"." << 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.
Plugin blacklist for plugins which can or should not be loaded.
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().