Improved plugin system:

- the user is asked at start wether to load or deny unregistered plugins, but can make it mind later in config->plugins
- added API and SVN numbers into required external plugin symbols
- user-defined plugin rules are dropped when a plugin changes (hash changes) or when the main executable changes.
- added new status flags (Plugin denied, missing API/SVN numbers)
- modified saveList()/loadList() to allow saving a list of rejected plugins as well.
- added methods in notifyBase and inherited classes to ask for plugin confirmation.

- adapted VOIP plugin to follow these new rules (API+SVN numbers). Other plugins should be adapted as well by addign the 
 missing symbols (RETROSHARE_PLUGIN_api and RETROSHARE_PLUGIN_revision).



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5529 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2012-09-09 13:59:21 +00:00
parent d57a75fbbd
commit 24a3fb58d4
13 changed files with 334 additions and 147 deletions

View File

@ -6,6 +6,7 @@
#include <serialiser/rstlvbase.h> #include <serialiser/rstlvbase.h>
#include <serialiser/rstlvtypes.h> #include <serialiser/rstlvtypes.h>
#include <serialiser/rspluginitems.h> #include <serialiser/rspluginitems.h>
#include <retroshare/rsiface.h>
#include <util/rsdir.h> #include <util/rsdir.h>
#include <util/folderiterator.h> #include <util/folderiterator.h>
#include <ft/ftserver.h> #include <ft/ftserver.h>
@ -23,8 +24,10 @@
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
std::string RsPluginManager::_plugin_entry_symbol ; std::string RsPluginManager::_plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ;
std::string RsPluginManager::_plugin_revision_symbol ; std::string RsPluginManager::_plugin_revision_symbol = "RETROSHARE_PLUGIN_revision" ;
std::string RsPluginManager::_plugin_API_symbol = "RETROSHARE_PLUGIN_api" ;
std::string RsPluginManager::_local_cache_dir ; std::string RsPluginManager::_local_cache_dir ;
std::string RsPluginManager::_remote_cache_dir ; std::string RsPluginManager::_remote_cache_dir ;
std::vector<std::string> RsPluginManager::_plugin_directories ; std::vector<std::string> RsPluginManager::_plugin_directories ;
@ -35,7 +38,8 @@ p3LinkMgr *RsPluginManager::_linkmgr = NULL ;
typedef RsPlugin *(*RetroSharePluginEntry)(void) ; typedef RsPlugin *(*RetroSharePluginEntry)(void) ;
RsPluginHandler *rsPlugins ; RsPluginHandler *rsPlugins ;
RsPluginManager::RsPluginManager() : p3Config(CONFIG_TYPE_PLUGINS) RsPluginManager::RsPluginManager(const std::string& hash)
: p3Config(CONFIG_TYPE_PLUGINS),_current_executable_hash(hash)
{ {
_allow_all_plugins = false ; _allow_all_plugins = false ;
} }
@ -133,7 +137,14 @@ void RsPluginManager::loadPlugins(const std::vector<std::string>& plugin_directo
dirIt.closedir(); dirIt.closedir();
} }
std::cerr << "Loaded a total of " << _plugins.size() << " plugins." << std::endl; std::cerr << "Examined a total of " << _plugins.size() << " plugins." << std::endl;
// Save list of accepted hashes and reference value
// Calling IndicateConfigChanged() at this point is not sufficient because the config flags are cleared
// at start of the p3config thread, and this thread has not yet started.
//
saveConfiguration();
} }
void RsPluginManager::getPluginStatus(int i,uint32_t& status,std::string& file_name,std::string& hash,uint32_t& svn_revision,std::string& error_string) const void RsPluginManager::getPluginStatus(int i,uint32_t& status,std::string& file_name,std::string& hash,uint32_t& svn_revision,std::string& error_string) const
@ -204,19 +215,39 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name)
std::cerr << " -> hashing." << std::endl; std::cerr << " -> hashing." << std::endl;
uint64_t size ; uint64_t size ;
// Stage 1 - get information related to file (hash, name, ...)
//
if(!RsDirUtil::getFileHash(plugin_name,pf.file_hash,size)) if(!RsDirUtil::getFileHash(plugin_name,pf.file_hash,size))
{ {
std::cerr << " -> cannot hash file. Plugin read canceled." << std::endl; std::cerr << " -> cannot hash file. Plugin read canceled." << std::endl;
return false; return false;
} }
// This file can be loaded. Insert an entry into the list of detected plugins.
//
_plugins.push_back(pf) ; _plugins.push_back(pf) ;
PluginInfo& pinfo(_plugins.back()) ; PluginInfo& pinfo(_plugins.back()) ;
std::cerr << " -> hash = " << pinfo.file_hash << std::endl; std::cerr << " -> hash = " << pinfo.file_hash << std::endl;
if(!_allow_all_plugins)
{
if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() )
if(!rsicontrol->getNotify().askForPluginConfirmation(pinfo.file_name,pinfo.file_hash))
_rejected_hashes.insert(pinfo.file_hash) ; // accepted hashes are treated at the end, for security.
if(_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() )
{
pinfo.status = PLUGIN_STATUS_REJECTED_HASH ;
std::cerr << " -> hash rejected. Giving up plugin. " << std::endl;
return false ;
}
}
else
std::cerr << " -> ALLOW_ALL_PLUGINS Enabled => plugin loaded by default." << std::endl;
std::cerr << " -> hash authorized. Loading plugin. " << std::endl;
// Stage 2 - open with dlopen, and get some basic info.
//
// The following choice is conservative by forcing RS to resolve all dependencies at // The following choice is conservative by forcing RS to resolve all dependencies at
// the time of loading the plugin. // the time of loading the plugin.
@ -234,16 +265,26 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name)
return false ; return false ;
} }
void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ;
pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ; void *papi = dlsym(handle,_plugin_API_symbol.c_str()) ; pinfo.API_version = (papi == NULL) ? 0 : (*(uint32_t *)papi) ;
std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl; std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl;
std::cerr << " -> retroshare svn number: " << SVN_REVISION_NUMBER << std::endl; std::cerr << " plugin API number : " << (void*)pinfo.API_version << std::endl;
std::cerr << " retroshare svn number: " << SVN_REVISION_NUMBER << std::endl;
if( (pinfo.svn_revision == 0 || pinfo.svn_revision != SVN_REVISION_NUMBER) && (!_allow_all_plugins) && _accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end()) // Check that the plugin provides a svn revision number and a API number
//
if(pinfo.API_version == 0)
{ {
std::cerr << " -> revision numbers do not match, and hash is not in white list. Plugin is rejected. Go to config->plugins to authorise this plugin." << std::endl; std::cerr << " -> No API version number." << std::endl;
pinfo.status = PLUGIN_STATUS_UNKNOWN_HASH ; pinfo.status = PLUGIN_STATUS_MISSING_API ;
pinfo.info_string = "" ;
return false ;
}
if(pinfo.svn_revision == 0)
{
std::cerr << " -> No svn revision number." << std::endl;
pinfo.status = PLUGIN_STATUS_MISSING_SVN ;
pinfo.info_string = "" ; pinfo.info_string = "" ;
return false ; return false ;
} }
@ -256,10 +297,10 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name)
{ {
std::cerr << dlerror() << std::endl ; std::cerr << dlerror() << std::endl ;
pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ; pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ;
pinfo.info_string = "Symbol " + _plugin_entry_symbol + " is missing." ; pinfo.info_string = _plugin_entry_symbol ;
return false ; return false ;
} }
std::cerr << " Added function entry for symbol " << _plugin_entry_symbol << std::endl ; std::cerr << " -> Added function entry for symbol " << _plugin_entry_symbol << std::endl ;
RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ; RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ;
@ -276,6 +317,7 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name)
p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries
pinfo.info_string = "" ; pinfo.info_string = "" ;
_accepted_hashes.insert(pinfo.file_hash) ; // do it now, to avoid putting in list a plugin that might have crashed during the load.
return true; return true;
} }
@ -355,56 +397,91 @@ void RsPluginManager::addConfigurations(p3ConfigMgr *ConfigMgr)
bool RsPluginManager::loadList(std::list<RsItem*>& list) bool RsPluginManager::loadList(std::list<RsItem*>& list)
{ {
_accepted_hashes.clear() ; std::set<std::string> accepted_hash_candidates ;
std::set<std::string> rejected_hash_candidates ;
std::cerr << "RsPluginManager::loadList(): " << std::endl; std::cerr << "RsPluginManager::loadList(): " << std::endl;
std::string reference_executable_hash = "" ;
std::list<RsItem *>::iterator it; std::list<RsItem *>::iterator it;
for(it = list.begin(); it != list.end(); it++) for(it = list.begin(); it != list.end(); it++)
{ {
RsPluginHashSetItem *vitem = dynamic_cast<RsPluginHashSetItem*>(*it);
if(vitem)
for(std::list<std::string>::const_iterator it(vitem->hashes.ids.begin());it!=vitem->hashes.ids.end();++it)
{
_accepted_hashes.insert(*it) ;
std::cerr << " loaded hash " << *it << std::endl;
}
RsConfigKeyValueSet *witem = dynamic_cast<RsConfigKeyValueSet *>(*it) ; RsConfigKeyValueSet *witem = dynamic_cast<RsConfigKeyValueSet *>(*it) ;
if(witem) if(witem)
{
for(std::list<RsTlvKeyValue>::const_iterator kit = witem->tlvkvs.pairs.begin(); kit != witem->tlvkvs.pairs.end(); ++kit) for(std::list<RsTlvKeyValue>::const_iterator kit = witem->tlvkvs.pairs.begin(); kit != witem->tlvkvs.pairs.end(); ++kit)
{
if((*kit).key == "ALLOW_ALL_PLUGINS") if((*kit).key == "ALLOW_ALL_PLUGINS")
{ {
std::cerr << "WARNING: Allowing all plugins. No hash will be checked. Be careful! " << std::endl ;
_allow_all_plugins = (kit->value == "YES"); _allow_all_plugins = (kit->value == "YES");
if(_allow_all_plugins)
std::cerr << "WARNING: Allowing all plugins. No hash will be checked. Be careful! " << std::endl ;
}
else if((*kit).key == "REFERENCE_EXECUTABLE_HASH")
{
reference_executable_hash = kit->value ;
std::cerr << " Reference executable hash: " << kit->value << std::endl;
}
else if((*kit).key == "ACCEPTED")
{
accepted_hash_candidates.insert((*kit).value) ;
std::cerr << " Accepted hash: " << (*kit).value << std::endl;
}
else if((*kit).key == "REJECTED")
{
rejected_hash_candidates.insert((*kit).value) ;
std::cerr << " Rejected hash: " << (*kit).value << std::endl;
} }
} }
delete (*it); delete (*it);
} }
if(reference_executable_hash == _current_executable_hash)
{
std::cerr << "(II) Executable hash matches. Updating the list of accepted/rejected plugins." << std::endl;
_accepted_hashes = accepted_hash_candidates ;
_rejected_hashes = rejected_hash_candidates ;
}
else
std::cerr << "(WW) Executable hashes do not match. Executable hash has changed. Discarding the list of accepted/rejected plugins." << std::endl;
return true; return true;
} }
bool RsPluginManager::saveList(bool& cleanup, std::list<RsItem*>& list) bool RsPluginManager::saveList(bool& cleanup, std::list<RsItem*>& list)
{ {
std::cerr << "PluginManager: saving list." << std::endl;
cleanup = true ; cleanup = true ;
RsPluginHashSetItem *vitem = new RsPluginHashSetItem() ;
for(std::set<std::string>::const_iterator it(_accepted_hashes.begin());it!=_accepted_hashes.end();++it)
vitem->hashes.ids.push_back(*it) ;
list.push_back(vitem) ;
RsConfigKeyValueSet *witem = new RsConfigKeyValueSet ; RsConfigKeyValueSet *witem = new RsConfigKeyValueSet ;
RsTlvKeyValue kv; RsTlvKeyValue kv;
kv.key = "ALLOW_ALL_PLUGINS" ; kv.key = "ALLOW_ALL_PLUGINS" ;
kv.value = _allow_all_plugins?"YES":"NO" ; kv.value = _allow_all_plugins?"YES":"NO" ;
witem->tlvkvs.pairs.push_back(kv) ; witem->tlvkvs.pairs.push_back(kv) ;
kv.key = "REFERENCE_EXECUTABLE_HASH" ;
kv.value = _current_executable_hash ;
witem->tlvkvs.pairs.push_back(kv) ;
std::cerr << " Saving current executable hash: " << kv.value << std::endl;
// now push accepted and rejected hashes.
for(std::set<std::string>::const_iterator it(_accepted_hashes.begin());it!=_accepted_hashes.end();++it)
{
witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "ACCEPTED", *it ) ) ;
std::cerr << " " << *it << " : " << "ACCEPTED" << std::endl;
}
for(std::set<std::string>::const_iterator it(_rejected_hashes.begin());it!=_rejected_hashes.end();++it)
{
witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "REJECTED", *it ) ) ;
std::cerr << " " << *it << " : " << "REJECTED" << std::endl;
}
list.push_back(witem) ; list.push_back(witem) ;
return true; return true;

View File

@ -13,18 +13,32 @@ class p3LinkMgr ;
class PluginInfo class PluginInfo
{ {
public: public:
// Main object provided by the plugin. NULL is the plugin could not be loaded.
//
RsPlugin *plugin ; RsPlugin *plugin ;
std::string info_string ;
// Information related to the file. Do not require the plugin to be loaded nor the DSO to be openned.
//
std::string file_hash ; std::string file_hash ;
std::string file_name ; std::string file_name ;
uint32_t svn_revision ;
uint32_t status ; // Information coming from directly loaded symbols. The plugin is responsible for providing them.
//
std::string creator ; // creator of the plugin
std::string name ; // name of the plugin
uint32_t API_version ; // API version.
uint32_t svn_revision ; // Coming from scripts. Same svn version but changing hash could be a security issue.
// This info is filled when accessing the .so, and loading the plugin.
//
uint32_t status ; // See the flags in retroshare/rsplugin.h
std::string info_string ;
}; };
class RsPluginManager: public RsPluginHandler, public p3Config class RsPluginManager: public RsPluginHandler, public p3Config
{ {
public: public:
RsPluginManager() ; RsPluginManager(const std::string& current_executable_sha1_hash) ;
virtual ~RsPluginManager() {} virtual ~RsPluginManager() {}
// ------------ Derived from RsPluginHandler ----------------// // ------------ Derived from RsPluginHandler ----------------//
@ -61,7 +75,7 @@ class RsPluginManager: public RsPluginHandler, public p3Config
* @param interfaces * @param interfaces
*/ */
void setInterfaces(RsPlugInInterfaces& interfaces); void setInterfaces(RsPlugInInterfaces& interfaces);
static void setPluginEntrySymbol(const std::string& s) { _plugin_entry_symbol = s ; }
static bool acceptablePluginName(const std::string& s) ; static bool acceptablePluginName(const std::string& s) ;
static void setCacheDirectories(const std::string& local,const std::string& remote) ; static void setCacheDirectories(const std::string& local,const std::string& remote) ;
static void setFileServer(ftServer *ft) { _ftserver = ft ; } static void setFileServer(ftServer *ft) { _ftserver = ft ; }
@ -88,11 +102,24 @@ class RsPluginManager: public RsPluginHandler, public p3Config
std::string hashPlugin(const std::string& shared_library_name) ; std::string hashPlugin(const std::string& shared_library_name) ;
std::vector<PluginInfo> _plugins ; std::vector<PluginInfo> _plugins ;
std::set<std::string> _accepted_hashes ;
// Should allow
// - searching
// - saving all hash
//
// At start
// * load reference executable hash. Compare with current executable.
// - if different => flush all plugin hashes from cache
// - if equal,
//
std::set<std::string> _accepted_hashes ; // accepted hash values for reference executable hash.
std::set<std::string> _rejected_hashes ; // rejected hash values for reference executable hash.
std::string _current_executable_hash ; // At all times, the list of accepted plugins should be related to the current hash of the executable.
bool _allow_all_plugins ; bool _allow_all_plugins ;
static std::string _plugin_entry_symbol ; static std::string _plugin_entry_symbol ;
static std::string _plugin_revision_symbol ; static std::string _plugin_revision_symbol ;
static std::string _plugin_API_symbol ;
static std::string _remote_cache_dir ; static std::string _remote_cache_dir ;
static std::string _local_cache_dir ; static std::string _local_cache_dir ;
static ftServer *_ftserver ; static ftServer *_ftserver ;

View File

@ -206,6 +206,7 @@ class NotifyBase
virtual void notifyHistoryChanged(uint32_t /* msgId */, int /* type */) {} virtual void notifyHistoryChanged(uint32_t /* msgId */, int /* type */) {}
virtual bool askForPassword(const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */ ) { return false ;} virtual bool askForPassword(const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */ ) { return false ;}
virtual bool askForPluginConfirmation(const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */) { return false ;}
}; };
const int NOTIFY_LIST_NEIGHBOURS = 1; const int NOTIFY_LIST_NEIGHBOURS = 1;

View File

@ -52,14 +52,22 @@ class RsPQIService ;
class RsAutoUpdatePage ; class RsAutoUpdatePage ;
class PopupChatDialog ; class PopupChatDialog ;
// Plugin API version. Not used yet, but will be in the future the
// main value that decides for compatibility.
//
#define RS_PLUGIN_API_VERSION 0x000101
// Used for the status of plugins. // Used for the status of plugins.
// //
#define PLUGIN_STATUS_NO_STATUS 0x0000 #define PLUGIN_STATUS_NO_STATUS 0x0000
#define PLUGIN_STATUS_UNKNOWN_HASH 0x0001 #define PLUGIN_STATUS_REJECTED_HASH 0x0001
#define PLUGIN_STATUS_DLOPEN_ERROR 0x0002 #define PLUGIN_STATUS_DLOPEN_ERROR 0x0002
#define PLUGIN_STATUS_MISSING_SYMBOL 0x0003 #define PLUGIN_STATUS_MISSING_SYMBOL 0x0003
#define PLUGIN_STATUS_NULL_PLUGIN 0x0004 #define PLUGIN_STATUS_NULL_PLUGIN 0x0004
#define PLUGIN_STATUS_LOADED 0x0005 #define PLUGIN_STATUS_LOADED 0x0005
#define PLUGIN_STATUS_WRONG_API 0x0006
#define PLUGIN_STATUS_MISSING_API 0x0007
#define PLUGIN_STATUS_MISSING_SVN 0x0008
class RsPluginHandler; class RsPluginHandler;

View File

@ -86,6 +86,7 @@ class RsInitConfig
/* Directories (SetupBaseDir) */ /* Directories (SetupBaseDir) */
static std::string basedir; static std::string basedir;
static std::string homePath; static std::string homePath;
static std::string main_executable_hash;
#ifdef WINDOWS_SYS #ifdef WINDOWS_SYS
static bool portable; static bool portable;
static bool isWindowsXP; static bool isWindowsXP;
@ -151,6 +152,7 @@ static const int SSLPWD_LEN = 64;
std::list<accountId> RsInitConfig::accountIds; std::list<accountId> RsInitConfig::accountIds;
std::string RsInitConfig::preferedId; std::string RsInitConfig::preferedId;
std::string RsInitConfig::main_executable_hash;
rs_lock_handle_t RsInitConfig::lockHandle; rs_lock_handle_t RsInitConfig::lockHandle;
@ -599,6 +601,15 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
#endif #endif
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ /******************************** WINDOWS/UNIX SPECIFIC PART ******************/
// Hash the main executable.
uint64_t tmp_size ;
std::string tmp_name ;
if(!RsDirUtil::getFileHash(argv[0],RsInitConfig::main_executable_hash,tmp_size,NULL))
std::cerr << "Cannot hash executable! Plugins will not be loaded correctly." << std::endl;
else
std::cerr << "Hashed main executable: " << RsInitConfig::main_executable_hash << std::endl;
/* At this point we want to. /* At this point we want to.
* 1) Load up Dase Directory. * 1) Load up Dase Directory.
@ -2176,7 +2187,7 @@ int RsServer::StartupRetroShare()
// possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc.
#endif #endif
RsPluginManager *mPluginsManager = new RsPluginManager ; RsPluginManager *mPluginsManager = new RsPluginManager(RsInitConfig::main_executable_hash) ;
rsPlugins = mPluginsManager ; rsPlugins = mPluginsManager ;
mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager); mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager);

View File

@ -77,7 +77,7 @@ RsTlvBinaryData::RsTlvBinaryData(uint16_t t)
} }
RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b) RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b)
: tlvtype(b.tlvtype), bin_data(NULL), bin_len(0) { : tlvtype(b.tlvtype), bin_len(0) , bin_data(NULL) {
setBinData(b.bin_data, b.bin_len); setBinData(b.bin_data, b.bin_len);
} }

View File

@ -213,6 +213,7 @@ class RsTlvKeyValue: public RsTlvItem
{ {
public: public:
RsTlvKeyValue() { return; } RsTlvKeyValue() { return; }
RsTlvKeyValue(const std::string& k,const std::string& v): key(k),value(v) {}
virtual ~RsTlvKeyValue() { return; } virtual ~RsTlvKeyValue() { return; }
virtual uint32_t TlvSize(); virtual uint32_t TlvSize();
virtual void TlvClear(); virtual void TlvClear();

View File

@ -38,6 +38,12 @@ extern "C" {
// with same revision numbers, assuming that the revision numbers are up-to-date. // with same revision numbers, assuming that the revision numbers are up-to-date.
// //
uint32_t RETROSHARE_PLUGIN_revision = SVN_REVISION_NUMBER ; uint32_t RETROSHARE_PLUGIN_revision = SVN_REVISION_NUMBER ;
// This symbol contains the svn revision number grabbed from the executable.
// It will be tested by RS to load the plugin automatically, since it is safe to load plugins
// with same revision numbers, assuming that the revision numbers are up-to-date.
//
uint32_t RETROSHARE_PLUGIN_api = RS_PLUGIN_API_VERSION ;
} }
void VOIPPlugin::getPluginVersion(int& major,int& minor,int& svn_rev) const void VOIPPlugin::getPluginVersion(int& major,int& minor,int& svn_rev) const

View File

@ -167,6 +167,33 @@ bool NotifyQt::askForPassword(const std::string& key_details, bool prev_is_bad,
return false; return false;
} }
bool NotifyQt::askForPluginConfirmation(const std::string& plugin_file_name, const std::string& plugin_file_hash)
{
RsAutoUpdatePage::lockAllEvents() ;
QMessageBox dialog;
dialog.setWindowTitle(tr("Unregistered plugin/executable"));
QString text ;
text += tr( "RetroShare has detected an unregistered plugin. This happens in two cases:<UL><LI>Your RetroShare executable has changed.</LI><LI>The plugin has changed</LI></UL>Click on Yes to authorize this plugin, or No to deny it. You can change your mind later in Options -> Plugins, then restart." ) ;
text += "<UL>" ;
text += "<LI>Hash:\t" + QString::fromStdString(plugin_file_hash) + "</LI>" ;
text += "<LI>File:\t" + QString::fromStdString(plugin_file_name) + "</LI>";
text += "</UL>" ;
dialog.setText(text) ;
dialog.setWindowIcon(QIcon(":/images/rstray3.png"));
dialog.setStandardButtons(QMessageBox::Yes | QMessageBox::No) ;
int ret = dialog.exec();
RsAutoUpdatePage::unlockAllEvents() ;
if (ret == QMessageBox::Yes)
return true ;
else
return false;
}
void NotifyQt::notifyDiscInfoChanged() void NotifyQt::notifyDiscInfoChanged()
{ {

View File

@ -59,6 +59,7 @@ class NotifyQt: public QObject, public NotifyBase
virtual void notifyDownloadComplete(const std::string& fileHash); virtual void notifyDownloadComplete(const std::string& fileHash);
virtual void notifyDownloadCompleteCount(uint32_t count); virtual void notifyDownloadCompleteCount(uint32_t count);
virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password); virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password);
virtual bool askForPluginConfirmation(const std::string& plugin_filename, const std::string& plugin_file_hash);
/* Notify from GUI */ /* Notify from GUI */
void notifyChatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType); void notifyChatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType);

View File

@ -57,14 +57,24 @@ PluginsPage::PluginsPage(QWidget * parent, Qt::WFlags flags)
switch(status) switch(status)
{ {
case PLUGIN_STATUS_UNKNOWN_HASH: status_string = tr("SVN revision number ")+QString::number(svn_revision)+tr(" does not match current. Please manually enable the plugin at your own risk.") ; case PLUGIN_STATUS_REJECTED_HASH: status_string = tr("Hash rejected. Enable it manually and restart, if you need.") ;
break ; break ;
case PLUGIN_STATUS_MISSING_API: status_string = tr("No API number supplied. Please read plugin development manual.") ;
break ;
case PLUGIN_STATUS_MISSING_SVN: status_string = tr("No SVN number supplied. Please read plugin development manual.") ;
break ;
case PLUGIN_STATUS_DLOPEN_ERROR: status_string = tr("Loading error.") ; case PLUGIN_STATUS_DLOPEN_ERROR: status_string = tr("Loading error.") ;
break ; break ;
case PLUGIN_STATUS_MISSING_SYMBOL:status_string = tr("Missing symbol. Wrong version?") ; case PLUGIN_STATUS_MISSING_SYMBOL:status_string = tr("Missing symbol. Wrong version?") ;
break ; break ;
case PLUGIN_STATUS_NULL_PLUGIN: status_string = tr("No plugin object") ; case PLUGIN_STATUS_NULL_PLUGIN: status_string = tr("No plugin object") ;
break ; break ;
case PLUGIN_STATUS_LOADED: status_string = tr("Plugins is loaded.") ; case PLUGIN_STATUS_LOADED: status_string = tr("Plugins is loaded.") ;
break ; break ;
default: default:

View File

@ -23,7 +23,7 @@
* *
*/ */
#include <stdio.h>
#include "notifytxt.h" #include "notifytxt.h"
#include <retroshare/rspeers.h> #include <retroshare/rspeers.h>
#include <string.h> #include <string.h>
@ -84,6 +84,23 @@ void NotifyTxt::notifyChat()
return; return;
} }
bool NotifyTxt::askForPluginConfirmation(const std::string& plugin_file_name, const std::string& plugin_file_hash)
{
std::cerr << "The following plugin is not registered as accepted or denied. You probably upgraded the main executable or the plugin itself." << std::endl;
std::cerr << " Hash: " << plugin_file_hash << std::endl;
std::cerr << " File: " << plugin_file_name << std::endl;
char a = 0 ;
while(a != 'y' && a != 'n')
{
std::cerr << "Enable this plugin ? (y/n) :" ;
std::cerr.flush() ;
a = fgetc(stdin) ;
}
return a == 'y' ;
}
bool NotifyTxt::askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password) bool NotifyTxt::askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password)
{ {
char *passwd = getpass(("Please enter GPG password for key "+key_details+": ").c_str()) ; char *passwd = getpass(("Please enter GPG password for key "+key_details+": ").c_str()) ;

View File

@ -41,6 +41,7 @@ class NotifyTxt: public NotifyBase
virtual void notifyErrorMsg(int list, int sev, std::string msg); virtual void notifyErrorMsg(int list, int sev, std::string msg);
virtual void notifyChat(); virtual void notifyChat();
virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password); virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password);
virtual bool askForPluginConfirmation(const std::string& plugin_file, const std::string& plugin_hash);
private: private: