25#include "plugin_blacklist.h"
30#include <unordered_map>
33#include <wx/translation.h>
47static const char SEP =
'\\';
49static const char SEP =
'/';
62static const char*
const STD_HARD_MSG = _(R
"""(
63PlugIn %s, version %i.%i was detected.
64This version is known to be unstable and will not be loaded.
65Please update this PlugIn using the PlugIn manager master catalog.
68static const char*
const STD_SOFT_MSG = _(R
"""(
69PlugIn %s, version %i.%i was detected.
70This version is known to be unstable.
71Please update this PlugIn using the PlugIn manager master catalog.
74static const char*
const OCHART_OBSOLETED_MSG = _(R
"""(
75PlugIn %s, version %i.%i was detected.
76This plugin is obsolete, the o-charts plugin should be used
77instead. Please uninstall this plugin and install o-charts
78using 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}
102 : major(0), minor(0), status(plug_status::unblocked), message(
"") {};
104 block(
int _major,
int _minor)
105 : major(_major), minor(_minor), status(plug_status::unblocked),
111 status(cb.hard ? plug_status::hard : plug_status::soft),
117 if (major == -1)
return true;
118 if (_major == -1)
return false;
119 if (_major > major)
return false;
120 if (_minor > minor)
return false;
124 plug_data to_plug_data(std::string name) {
132static inline std::string normalize_lib(
const std::string& name) {
134 auto slashpos = libname.rfind(SEP);
135 if (slashpos != std::string::npos) libname = libname.substr(slashpos + 1);
136#if defined(__WXGTK__) || defined(__WXOSX__)
137 if (libname.find(
"lib") == 0) libname = libname.substr(3);
139 auto dotpos = libname.rfind(
'.');
140 if (dotpos != std::string::npos) libname = libname.substr(0, dotpos);
144static std::string to_lower(
const std::string& arg) {
146 std::transform(s.begin(), s.end(), s.begin(),
147 [](
unsigned char c){ return std::tolower(c); });
154friend std::unique_ptr<AbstractBlacklist> blacklist_factory();
156typedef std::unordered_map<std::string, block> block_map;
160 constexpr int list_len =
sizeof(plugin_blacklist)/
sizeof(
config_block);
161 for (
int i = 0; i < list_len; i += 1) {
162 m_blocks[plugin_blacklist[i].name] =
block(plugin_blacklist[i]);
168 block_map::iterator find_block(
const std::string& name) {
169 const auto s = to_lower(name);
170 for (
auto it = m_blocks.begin(); it != m_blocks.end(); it++) {
171 if (to_lower(it->first) == s)
return it;
173 return m_blocks.end();
176 bool update_block(
const std::string& name,
int major,
int minor) {
177 bool new_block =
false;
178 if (m_blocks.find(name) == m_blocks.end()) {
179 m_blocks[name] =
block(major, minor);
182 m_blocks[name].status = plug_status::unloadable;
183 m_blocks[name].major = major;
184 m_blocks[name].minor = minor;
189 std::string format_message(
const std::string msg,
const plug_data& data) {
190 int size = std::snprintf(
nullptr, 0, msg.c_str(),
191 data.name.c_str(), data.major, data.minor);
193 wxLogWarning(
"Cannot format message for %s", data.name.c_str());
194 return "Internal error: Cannot format message(!)";
196 std::unique_ptr<char[]> buf(
new char[size]);
197 std::snprintf(buf.get(), size, msg.c_str(),
198 data.name.c_str(), data.major, data.minor);
199 return std::string(buf.get(), buf.get() + size - 1);
205 std::string filename(normalize_lib(library_file));
206 auto found = find_block(filename);
207 if (found == m_blocks.end())
return plug_data(
"", -1, -1);
208 return plug_data(found->first, found->second.major, found->second.minor);
211 plug_status
get_status(
const std::string& name,
int major,
int minor) {
212 if (m_blocks.find(name) == m_blocks.end())
return plug_status::unblocked;
213 const auto& b = m_blocks[name];
214 return b.is_matching(major, minor) ? b.status : plug_status::unblocked;
218 return get_status(pd.name, pd.major, pd.minor);
222 int major,
int minor) {
223 return update_block(name, major, minor);
229 auto slashpos = filename.rfind(SEP);
230 if (slashpos != std::string::npos)
231 filename = filename.substr(slashpos + 1);
232 return update_block(filename, -1, -1);
237 auto slashpos = filename.rfind(SEP);
238 if (slashpos != std::string::npos) filename = filename.substr(slashpos + 1);
240 if (m_blocks.find(filename) == m_blocks.end())
return true;
241 return m_blocks[filename].status != plug_status::unloadable;
245#pragma GCC diagnostic push
246#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
248 if (status == plug_status::unloadable) {
249 std::string msg(_(
"Plugin library %s can not be loaded"));
250 msg = std::regex_replace(msg, std::regex(
"%s"), data.name);
253 if (status == plug_status::unblocked) {
254 wxLogMessage(
"Attempt to get message for unblocked plugin %s",
256 return "No applicable message";
258 auto found = find_block(data.name);
259 if (found == m_blocks.end())
260 return format_message(
"No known message for %s version %d.%d", data);
262 return format_message(found->second.message, data);
264#pragma GCC diagnostic pop
268std::unique_ptr<AbstractBlacklist> blacklist_factory() {
269 return std::unique_ptr<AbstractBlacklist>(
new PlugBlacklist());
279int main(
int argc,
char** argv) {
281 const std::string name(argv[1]);
282 int major = atoi(argv[2]);
283 int minor = atoi(argv[3]);
284 auto blacklist = blacklist_factory();
285 blacklist->mark_unloadable(
"foo");
286 auto s = blacklist->get_status(name, major, minor);
288 case plug_status::unloadable: std::cout <<
"unloadable\n";
break;
289 case plug_status::unblocked: std::cout <<
"unblocked\n";
break;
290 case plug_status::hard: std::cout <<
"hard\n";
break;
291 case plug_status::soft: std::cout <<
"soft\n";
break;
293 auto lib = blacklist->plugin_by_libname(name);
294 std::cout <<
"found plugin: \"" << lib.name <<
"\" version: " << lib.major
295 <<
"." << 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().