mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-24 15:09:33 -05:00
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:
parent
d57a75fbbd
commit
24a3fb58d4
@ -6,6 +6,7 @@
|
||||
#include <serialiser/rstlvbase.h>
|
||||
#include <serialiser/rstlvtypes.h>
|
||||
#include <serialiser/rspluginitems.h>
|
||||
#include <retroshare/rsiface.h>
|
||||
#include <util/rsdir.h>
|
||||
#include <util/folderiterator.h>
|
||||
#include <ft/ftserver.h>
|
||||
@ -23,8 +24,10 @@
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
std::string RsPluginManager::_plugin_entry_symbol ;
|
||||
std::string RsPluginManager::_plugin_revision_symbol ;
|
||||
std::string RsPluginManager::_plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ;
|
||||
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::_remote_cache_dir ;
|
||||
std::vector<std::string> RsPluginManager::_plugin_directories ;
|
||||
@ -35,7 +38,8 @@ p3LinkMgr *RsPluginManager::_linkmgr = NULL ;
|
||||
typedef RsPlugin *(*RetroSharePluginEntry)(void) ;
|
||||
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 ;
|
||||
}
|
||||
@ -133,7 +137,14 @@ void RsPluginManager::loadPlugins(const std::vector<std::string>& plugin_directo
|
||||
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
|
||||
@ -204,79 +215,110 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name)
|
||||
std::cerr << " -> hashing." << std::endl;
|
||||
uint64_t size ;
|
||||
|
||||
// Stage 1 - get information related to file (hash, name, ...)
|
||||
//
|
||||
if(!RsDirUtil::getFileHash(plugin_name,pf.file_hash,size))
|
||||
{
|
||||
std::cerr << " -> cannot hash file. Plugin read canceled." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This file can be loaded. Insert an entry into the list of detected plugins.
|
||||
//
|
||||
_plugins.push_back(pf) ;
|
||||
PluginInfo& pinfo(_plugins.back()) ;
|
||||
|
||||
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.
|
||||
|
||||
// The following choice is conservative by forcing RS to resolve all dependencies at
|
||||
// the time of loading the plugin.
|
||||
|
||||
int link_mode = RTLD_NOW | RTLD_GLOBAL ;
|
||||
|
||||
void *handle = dlopen(plugin_name.c_str(),link_mode) ;
|
||||
|
||||
if(handle == NULL)
|
||||
if(_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() )
|
||||
{
|
||||
const char *val = dlerror() ;
|
||||
std::cerr << " Cannot open plugin: " << val << std::endl ;
|
||||
pinfo.status = PLUGIN_STATUS_DLOPEN_ERROR ;
|
||||
pinfo.info_string = val ;
|
||||
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;
|
||||
|
||||
void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ;
|
||||
pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ;
|
||||
std::cerr << " -> hash authorized. Loading plugin. " << std::endl;
|
||||
|
||||
std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl;
|
||||
std::cerr << " -> retroshare svn number: " << SVN_REVISION_NUMBER << std::endl;
|
||||
// Stage 2 - open with dlopen, and get some basic info.
|
||||
//
|
||||
|
||||
if( (pinfo.svn_revision == 0 || pinfo.svn_revision != SVN_REVISION_NUMBER) && (!_allow_all_plugins) && _accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end())
|
||||
{
|
||||
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;
|
||||
pinfo.status = PLUGIN_STATUS_UNKNOWN_HASH ;
|
||||
pinfo.info_string = "" ;
|
||||
return false ;
|
||||
}
|
||||
// The following choice is conservative by forcing RS to resolve all dependencies at
|
||||
// the time of loading the plugin.
|
||||
|
||||
// Now look for the plugin class symbol.
|
||||
//
|
||||
void *pfe = dlsym(handle,_plugin_entry_symbol.c_str()) ;
|
||||
int link_mode = RTLD_NOW | RTLD_GLOBAL ;
|
||||
|
||||
if(pfe == NULL)
|
||||
{
|
||||
std::cerr << dlerror() << std::endl ;
|
||||
pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ;
|
||||
pinfo.info_string = "Symbol " + _plugin_entry_symbol + " is missing." ;
|
||||
return false ;
|
||||
}
|
||||
std::cerr << " Added function entry for symbol " << _plugin_entry_symbol << std::endl ;
|
||||
void *handle = dlopen(plugin_name.c_str(),link_mode) ;
|
||||
|
||||
RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ;
|
||||
if(handle == NULL)
|
||||
{
|
||||
const char *val = dlerror() ;
|
||||
std::cerr << " Cannot open plugin: " << val << std::endl ;
|
||||
pinfo.status = PLUGIN_STATUS_DLOPEN_ERROR ;
|
||||
pinfo.info_string = val ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
if(p == NULL)
|
||||
{
|
||||
std::cerr << " Plugin entry function " << _plugin_entry_symbol << " returns NULL ! It should return an object of type RsPlugin* " << std::endl;
|
||||
pinfo.status = PLUGIN_STATUS_NULL_PLUGIN ;
|
||||
pinfo.info_string = "Plugin entry " + _plugin_entry_symbol + "() return NULL" ;
|
||||
return false ;
|
||||
}
|
||||
void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; 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) ;
|
||||
|
||||
pinfo.status = PLUGIN_STATUS_LOADED ;
|
||||
pinfo.plugin = p ;
|
||||
p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries
|
||||
std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl;
|
||||
std::cerr << " plugin API number : " << (void*)pinfo.API_version << std::endl;
|
||||
std::cerr << " retroshare svn number: " << SVN_REVISION_NUMBER << std::endl;
|
||||
|
||||
// Check that the plugin provides a svn revision number and a API number
|
||||
//
|
||||
if(pinfo.API_version == 0)
|
||||
{
|
||||
std::cerr << " -> No API version number." << std::endl;
|
||||
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 = "" ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Now look for the plugin class symbol.
|
||||
//
|
||||
void *pfe = dlsym(handle,_plugin_entry_symbol.c_str()) ;
|
||||
|
||||
if(pfe == NULL)
|
||||
{
|
||||
std::cerr << dlerror() << std::endl ;
|
||||
pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ;
|
||||
pinfo.info_string = _plugin_entry_symbol ;
|
||||
return false ;
|
||||
}
|
||||
std::cerr << " -> Added function entry for symbol " << _plugin_entry_symbol << std::endl ;
|
||||
|
||||
RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ;
|
||||
|
||||
if(p == NULL)
|
||||
{
|
||||
std::cerr << " Plugin entry function " << _plugin_entry_symbol << " returns NULL ! It should return an object of type RsPlugin* " << std::endl;
|
||||
pinfo.status = PLUGIN_STATUS_NULL_PLUGIN ;
|
||||
pinfo.info_string = "Plugin entry " + _plugin_entry_symbol + "() return NULL" ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
pinfo.status = PLUGIN_STATUS_LOADED ;
|
||||
pinfo.plugin = p ;
|
||||
p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries
|
||||
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;
|
||||
}
|
||||
|
||||
p3LinkMgr *RsPluginManager::getLinkMgr() const
|
||||
@ -355,56 +397,91 @@ void RsPluginManager::addConfigurations(p3ConfigMgr *ConfigMgr)
|
||||
|
||||
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::string reference_executable_hash = "" ;
|
||||
|
||||
std::list<RsItem *>::iterator 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) ;
|
||||
|
||||
if(witem)
|
||||
{
|
||||
for(std::list<RsTlvKeyValue>::const_iterator kit = witem->tlvkvs.pairs.begin(); kit != witem->tlvkvs.pairs.end(); ++kit)
|
||||
{
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool RsPluginManager::saveList(bool& cleanup, std::list<RsItem*>& list)
|
||||
{
|
||||
std::cerr << "PluginManager: saving list." << std::endl;
|
||||
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 ;
|
||||
RsTlvKeyValue kv;
|
||||
kv.key = "ALLOW_ALL_PLUGINS" ;
|
||||
kv.value = _allow_all_plugins?"YES":"NO" ;
|
||||
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) ;
|
||||
|
||||
return true;
|
||||
|
@ -13,18 +13,32 @@ class p3LinkMgr ;
|
||||
class PluginInfo
|
||||
{
|
||||
public:
|
||||
// Main object provided by the plugin. NULL is the plugin could not be loaded.
|
||||
//
|
||||
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_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
|
||||
{
|
||||
public:
|
||||
RsPluginManager() ;
|
||||
RsPluginManager(const std::string& current_executable_sha1_hash) ;
|
||||
virtual ~RsPluginManager() {}
|
||||
|
||||
// ------------ Derived from RsPluginHandler ----------------//
|
||||
@ -60,8 +74,8 @@ class RsPluginManager: public RsPluginHandler, public p3Config
|
||||
* sets interfaces for all loaded plugins
|
||||
* @param interfaces
|
||||
*/
|
||||
void setInterfaces(RsPlugInInterfaces& interfaces);
|
||||
static void setPluginEntrySymbol(const std::string& s) { _plugin_entry_symbol = s ; }
|
||||
void setInterfaces(RsPlugInInterfaces& interfaces);
|
||||
|
||||
static bool acceptablePluginName(const std::string& s) ;
|
||||
static void setCacheDirectories(const std::string& local,const std::string& remote) ;
|
||||
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::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 ;
|
||||
|
||||
static std::string _plugin_entry_symbol ;
|
||||
static std::string _plugin_revision_symbol ;
|
||||
static std::string _plugin_API_symbol ;
|
||||
static std::string _remote_cache_dir ;
|
||||
static std::string _local_cache_dir ;
|
||||
static ftServer *_ftserver ;
|
||||
|
@ -206,6 +206,7 @@ class NotifyBase
|
||||
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 askForPluginConfirmation(const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */) { return false ;}
|
||||
};
|
||||
|
||||
const int NOTIFY_LIST_NEIGHBOURS = 1;
|
||||
|
@ -52,14 +52,22 @@ class RsPQIService ;
|
||||
class RsAutoUpdatePage ;
|
||||
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.
|
||||
//
|
||||
#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_MISSING_SYMBOL 0x0003
|
||||
#define PLUGIN_STATUS_NULL_PLUGIN 0x0004
|
||||
#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;
|
||||
|
||||
|
@ -86,6 +86,7 @@ class RsInitConfig
|
||||
/* Directories (SetupBaseDir) */
|
||||
static std::string basedir;
|
||||
static std::string homePath;
|
||||
static std::string main_executable_hash;
|
||||
#ifdef WINDOWS_SYS
|
||||
static bool portable;
|
||||
static bool isWindowsXP;
|
||||
@ -151,6 +152,7 @@ static const int SSLPWD_LEN = 64;
|
||||
|
||||
std::list<accountId> RsInitConfig::accountIds;
|
||||
std::string RsInitConfig::preferedId;
|
||||
std::string RsInitConfig::main_executable_hash;
|
||||
|
||||
rs_lock_handle_t RsInitConfig::lockHandle;
|
||||
|
||||
@ -599,6 +601,15 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
|
||||
#endif
|
||||
/******************************** 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.
|
||||
* 1) Load up Dase Directory.
|
||||
@ -1888,7 +1899,7 @@ int RsServer::StartupRetroShare()
|
||||
/* (1) Load up own certificate (DONE ALREADY) - just CHECK */
|
||||
/**************************************************************************/
|
||||
|
||||
if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL))
|
||||
if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL))
|
||||
{
|
||||
std::cerr << "main() - Fatal Error....." << std::endl;
|
||||
std::cerr << "Invalid Certificate configuration!" << std::endl;
|
||||
@ -1896,15 +1907,15 @@ int RsServer::StartupRetroShare()
|
||||
return false ;
|
||||
}
|
||||
|
||||
std::string ownId = AuthSSL::getAuthSSL()->OwnId();
|
||||
std::string ownId = AuthSSL::getAuthSSL()->OwnId();
|
||||
|
||||
/**************************************************************************/
|
||||
/* Any Initial Configuration (Commandline Options) */
|
||||
/**************************************************************************/
|
||||
|
||||
/* set the debugging to crashMode */
|
||||
std::cerr << "set the debugging to crashMode." << std::endl;
|
||||
if ((!RsInitConfig::haveLogFile) && (!RsInitConfig::outStderr))
|
||||
std::cerr << "set the debugging to crashMode." << std::endl;
|
||||
if ((!RsInitConfig::haveLogFile) && (!RsInitConfig::outStderr))
|
||||
{
|
||||
std::string crashfile = RsInitConfig::basedir + "/";
|
||||
crashfile += ownId + "/" + configLogFileName;
|
||||
@ -1919,7 +1930,7 @@ int RsServer::StartupRetroShare()
|
||||
|
||||
/**************************************************************************/
|
||||
// Load up Certificates, and Old Configuration (if present)
|
||||
std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl;
|
||||
std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl;
|
||||
|
||||
std::string emergencySaveDir = RsInitConfig::configDir.c_str();
|
||||
std::string emergencyPartialsDir = RsInitConfig::configDir.c_str();
|
||||
@ -1934,7 +1945,7 @@ int RsServer::StartupRetroShare()
|
||||
/**************************************************************************/
|
||||
/* setup classes / structures */
|
||||
/**************************************************************************/
|
||||
std::cerr << "setup classes / structures" << std::endl;
|
||||
std::cerr << "setup classes / structures" << std::endl;
|
||||
|
||||
|
||||
|
||||
@ -1944,21 +1955,21 @@ int RsServer::StartupRetroShare()
|
||||
mNetMgr = new p3NetMgrIMPL();
|
||||
mLinkMgr = new p3LinkMgrIMPL(mPeerMgr, mNetMgr);
|
||||
|
||||
/* Setup Notify Early - So we can use it. */
|
||||
rsNotify = new p3Notify();
|
||||
rsPeers = new p3Peers(mLinkMgr, mPeerMgr, mNetMgr);
|
||||
/* Setup Notify Early - So we can use it. */
|
||||
rsNotify = new p3Notify();
|
||||
rsPeers = new p3Peers(mLinkMgr, mPeerMgr, mNetMgr);
|
||||
|
||||
mPeerMgr->setManagers(mLinkMgr, mNetMgr);
|
||||
mNetMgr->setManagers(mPeerMgr, mLinkMgr);
|
||||
|
||||
//load all the SSL certs as friends
|
||||
// std::list<std::string> sslIds;
|
||||
// AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds);
|
||||
// for (std::list<std::string>::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); sslIdsIt++) {
|
||||
// mConnMgr->addFriend(*sslIdsIt);
|
||||
// }
|
||||
//p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, RsInitConfig::configDir);
|
||||
/**************************** BITDHT ***********************************/
|
||||
|
||||
//load all the SSL certs as friends
|
||||
// std::list<std::string> sslIds;
|
||||
// AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds);
|
||||
// for (std::list<std::string>::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); sslIdsIt++) {
|
||||
// mConnMgr->addFriend(*sslIdsIt);
|
||||
// }
|
||||
//p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, RsInitConfig::configDir);
|
||||
/**************************** BITDHT ***********************************/
|
||||
|
||||
// Make up an address. XXX
|
||||
|
||||
@ -2058,13 +2069,13 @@ int RsServer::StartupRetroShare()
|
||||
p3BitDht *mBitDht = new p3BitDht(ownId, mLinkMgr, mNetMgr, mDhtStack, bootstrapfile);
|
||||
/* install external Pointer for Interface */
|
||||
rsDht = mBitDht;
|
||||
|
||||
|
||||
// NEXT THE RELAY (NEED to keep a reference for installing RELAYS)
|
||||
UdpRelayReceiver *mRelay = new UdpRelayReceiver(mDhtStack);
|
||||
udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX] = mRelay; /* RELAY Connections (DHT Port) */
|
||||
udpTypes[RSUDP_TOU_RECVER_RELAY_IDX] = TOU_RECEIVER_TYPE_UDPRELAY;
|
||||
mDhtStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX]);
|
||||
|
||||
|
||||
// LAST ON THIS STACK IS STANDARD DIRECT TOU
|
||||
udpReceivers[RSUDP_TOU_RECVER_DIRECT_IDX] = new UdpPeerReceiver(mDhtStack); /* standard DIRECT Connections (DHT Port) */
|
||||
udpTypes[RSUDP_TOU_RECVER_DIRECT_IDX] = TOU_RECEIVER_TYPE_UDPPEER;
|
||||
@ -2073,19 +2084,19 @@ int RsServer::StartupRetroShare()
|
||||
// NOW WE BUILD THE SECOND STACK.
|
||||
// Create the Second UdpStack... Port should be random (but openable!).
|
||||
|
||||
//#define MIN_RANDOM_PORT 30000
|
||||
//#define MAX_RANDOM_PORT 50000
|
||||
|
||||
//#define MIN_RANDOM_PORT 30000
|
||||
//#define MAX_RANDOM_PORT 50000
|
||||
|
||||
struct sockaddr_in sndladdr;
|
||||
sockaddr_clear(&sndladdr);
|
||||
|
||||
// #ifdef LOCALNET_TESTING
|
||||
// // HACK Proxy Port near Dht Port - For Relay Testing.
|
||||
// uint16_t rndport = RsInitConfig::port + 3;
|
||||
// sndladdr.sin_port = htons(rndport);
|
||||
// #else
|
||||
// uint16_t rndport = MIN_RANDOM_PORT + RSRandom::random_u32() % (MAX_RANDOM_PORT - MIN_RANDOM_PORT);
|
||||
// #endif
|
||||
// #ifdef LOCALNET_TESTING
|
||||
// // HACK Proxy Port near Dht Port - For Relay Testing.
|
||||
// uint16_t rndport = RsInitConfig::port + 3;
|
||||
// sndladdr.sin_port = htons(rndport);
|
||||
// #else
|
||||
// uint16_t rndport = MIN_RANDOM_PORT + RSRandom::random_u32() % (MAX_RANDOM_PORT - MIN_RANDOM_PORT);
|
||||
// #endif
|
||||
|
||||
#ifdef LOCALNET_TESTING
|
||||
|
||||
@ -2104,23 +2115,23 @@ int RsServer::StartupRetroShare()
|
||||
// FIRSTLY THE PROXY STUNNER.
|
||||
UdpStunner *mProxyStunner = new UdpStunner(mProxyStack);
|
||||
mProxyStunner->setTargetStunPeriod(300); /* slow (5mins) */
|
||||
mProxyStack->addReceiver(mProxyStunner);
|
||||
mProxyStack->addReceiver(mProxyStunner);
|
||||
|
||||
#ifdef LOCALNET_TESTING
|
||||
mProxyStunner->SetAcceptLocalNet();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// FINALLY THE PROXY UDP CONNECTIONS
|
||||
udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX] = new UdpPeerReceiver(mProxyStack); /* PROXY Connections (Alt UDP Port) */
|
||||
udpTypes[RSUDP_TOU_RECVER_PROXY_IDX] = TOU_RECEIVER_TYPE_UDPPEER;
|
||||
mProxyStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX]);
|
||||
|
||||
|
||||
// REAL INITIALISATION - WITH THREE MODES
|
||||
tou_init((void **) udpReceivers, udpTypes, RSUDP_NUM_TOU_RECVERS);
|
||||
|
||||
mBitDht->setupConnectBits(mDhtStunner, mProxyStunner, mRelay);
|
||||
|
||||
|
||||
mNetMgr->setAddrAssist(new stunAddrAssist(mDhtStunner), new stunAddrAssist(mProxyStunner));
|
||||
#else
|
||||
/* install NULL Pointer for rsDht Interface */
|
||||
@ -2128,7 +2139,7 @@ int RsServer::StartupRetroShare()
|
||||
#endif
|
||||
|
||||
|
||||
/**************************** BITDHT ***********************************/
|
||||
/**************************** BITDHT ***********************************/
|
||||
|
||||
|
||||
SecurityPolicy *none = secpolicy_create();
|
||||
@ -2150,7 +2161,7 @@ int RsServer::StartupRetroShare()
|
||||
|
||||
/* This should be set by config ... there is no default */
|
||||
//ftserver->setSharedDirectories(fileList);
|
||||
|
||||
|
||||
rsFiles = ftserver;
|
||||
|
||||
|
||||
@ -2173,10 +2184,10 @@ int RsServer::StartupRetroShare()
|
||||
plugins_directories.push_back(RsInitConfig::basedir + "/extensions/") ;
|
||||
#ifdef DEBUG_PLUGIN_SYSTEM
|
||||
plugins_directories.push_back(".") ; // this list should be saved/set to some correct value.
|
||||
// possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc.
|
||||
// possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc.
|
||||
#endif
|
||||
|
||||
RsPluginManager *mPluginsManager = new RsPluginManager ;
|
||||
RsPluginManager *mPluginsManager = new RsPluginManager(RsInitConfig::main_executable_hash) ;
|
||||
rsPlugins = mPluginsManager ;
|
||||
mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager);
|
||||
|
||||
@ -2197,7 +2208,7 @@ int RsServer::StartupRetroShare()
|
||||
// - developping plugins
|
||||
//
|
||||
std::vector<RsPlugin *> programatically_inserted_plugins ;
|
||||
|
||||
|
||||
// Push your own plugins into this list, before the call:
|
||||
//
|
||||
// programatically_inserted_plugins.push_back(myCoolPlugin) ;
|
||||
@ -2217,7 +2228,7 @@ int RsServer::StartupRetroShare()
|
||||
mStatusSrv = new p3StatusService(mLinkMgr);
|
||||
|
||||
#ifndef PQI_DISABLE_TUNNEL
|
||||
p3tunnel *tn = new p3tunnel(mConnMgr, pqih);
|
||||
p3tunnel *tn = new p3tunnel(mConnMgr, pqih);
|
||||
pqih -> addService(tn);
|
||||
mConnMgr->setP3tunnel(tn);
|
||||
#endif
|
||||
@ -2259,23 +2270,23 @@ int RsServer::StartupRetroShare()
|
||||
// Testing New Cache Services.
|
||||
p3PhotoService *mPhotos = new p3PhotoService(RS_SERVICE_TYPE_PHOTO);
|
||||
pqih -> addService(mPhotos);
|
||||
|
||||
|
||||
// Testing New Cache Services.
|
||||
p3WikiService *mWikis = new p3WikiService(RS_SERVICE_TYPE_WIKI);
|
||||
pqih -> addService(mWikis);
|
||||
|
||||
|
||||
// Testing New Cache Services.
|
||||
p3Wire *mWire = new p3Wire(RS_SERVICE_TYPE_WIRE);
|
||||
pqih -> addService(mWire);
|
||||
|
||||
|
||||
// Testing New Cache Services.
|
||||
p3IdService *mIdentity = new p3IdService(RS_SERVICE_TYPE_IDENTITY);
|
||||
pqih -> addService(mIdentity);
|
||||
|
||||
|
||||
// Testing New Cache Services.
|
||||
p3ForumsV2 *mForumsV2 = new p3ForumsV2(RS_SERVICE_TYPE_FORUMSV2);
|
||||
pqih -> addService(mForumsV2);
|
||||
|
||||
|
||||
// Testing New Cache Services.
|
||||
p3PostedService *mPosted = new p3PostedService(RS_SERVICE_TYPE_POSTED);
|
||||
pqih -> addService(mPosted);
|
||||
@ -2319,8 +2330,8 @@ int RsServer::StartupRetroShare()
|
||||
|
||||
#ifdef RS_ENABLE_ZEROCONF
|
||||
p3ZeroConf *mZeroConf = new p3ZeroConf(
|
||||
AuthGPG::getAuthGPG()->getGPGOwnId(), ownId,
|
||||
mLinkMgr, mNetMgr, mPeerMgr);
|
||||
AuthGPG::getAuthGPG()->getGPGOwnId(), ownId,
|
||||
mLinkMgr, mNetMgr, mPeerMgr);
|
||||
mNetMgr->addNetAssistConnect(2, mZeroConf);
|
||||
mNetMgr->addNetListener(mZeroConf);
|
||||
#endif
|
||||
@ -2384,7 +2395,7 @@ int RsServer::StartupRetroShare()
|
||||
/**************************************************************************/
|
||||
/* (2) Load configuration files */
|
||||
/**************************************************************************/
|
||||
std::cerr << "(2) Load configuration files" << std::endl;
|
||||
std::cerr << "(2) Load configuration files" << std::endl;
|
||||
|
||||
mConfigMgr->loadConfiguration();
|
||||
|
||||
@ -2398,12 +2409,12 @@ int RsServer::StartupRetroShare()
|
||||
/**************************************************************************/
|
||||
pqih->setConfig(mGeneralConfig);
|
||||
|
||||
pqih->load_config();
|
||||
pqih->load_config();
|
||||
|
||||
/**************************************************************************/
|
||||
/* Force Any Configuration before Startup (After Load) */
|
||||
/**************************************************************************/
|
||||
std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl;
|
||||
std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl;
|
||||
|
||||
if (RsInitConfig::forceLocalAddr)
|
||||
{
|
||||
@ -2411,7 +2422,7 @@ int RsServer::StartupRetroShare()
|
||||
|
||||
/* clean sockaddr before setting values (MaxOSX) */
|
||||
sockaddr_clear(&laddr);
|
||||
|
||||
|
||||
laddr.sin_family = AF_INET;
|
||||
laddr.sin_port = htons(RsInitConfig::port);
|
||||
|
||||
@ -2436,7 +2447,7 @@ int RsServer::StartupRetroShare()
|
||||
if (load_trustedpeer)
|
||||
{
|
||||
/* sslroot does further checks */
|
||||
sslr -> loadInitialTrustedPeer(load_trustedpeer_file);
|
||||
sslr -> loadInitialTrustedPeer(load_trustedpeer_file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2480,7 +2491,7 @@ int RsServer::StartupRetroShare()
|
||||
/* flag that the basic Caches are now in the pending Queues */
|
||||
mForums->HistoricalCachesDone();
|
||||
mChannels->HistoricalCachesDone();
|
||||
|
||||
|
||||
#ifdef RS_USE_BLOGS
|
||||
mBlogs->HistoricalCachesDone();
|
||||
#endif
|
||||
@ -2502,9 +2513,9 @@ int RsServer::StartupRetroShare()
|
||||
ftserver->StartupThreads();
|
||||
ftserver->ResumeTransfers();
|
||||
|
||||
//mDhtMgr->start();
|
||||
//mDhtMgr->start();
|
||||
#ifdef RS_USE_BITDHT
|
||||
mBitDht->start();
|
||||
mBitDht->start();
|
||||
#endif
|
||||
|
||||
// startup the p3distrib threads (for cache loading).
|
||||
|
@ -77,7 +77,7 @@ RsTlvBinaryData::RsTlvBinaryData(uint16_t t)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ class RsTlvKeyValue: public RsTlvItem
|
||||
{
|
||||
public:
|
||||
RsTlvKeyValue() { return; }
|
||||
RsTlvKeyValue(const std::string& k,const std::string& v): key(k),value(v) {}
|
||||
virtual ~RsTlvKeyValue() { return; }
|
||||
virtual uint32_t TlvSize();
|
||||
virtual void TlvClear();
|
||||
|
@ -38,6 +38,12 @@ extern "C" {
|
||||
// with same revision numbers, assuming that the revision numbers are up-to-date.
|
||||
//
|
||||
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
|
||||
|
@ -167,6 +167,33 @@ bool NotifyQt::askForPassword(const std::string& key_details, bool prev_is_bad,
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -59,6 +59,7 @@ class NotifyQt: public QObject, public NotifyBase
|
||||
virtual void notifyDownloadComplete(const std::string& fileHash);
|
||||
virtual void notifyDownloadCompleteCount(uint32_t count);
|
||||
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 */
|
||||
void notifyChatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType);
|
||||
|
@ -57,16 +57,26 @@ PluginsPage::PluginsPage(QWidget * parent, Qt::WFlags flags)
|
||||
|
||||
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.") ;
|
||||
break ;
|
||||
case PLUGIN_STATUS_DLOPEN_ERROR: status_string = tr("Loading error.") ;
|
||||
break ;
|
||||
case PLUGIN_STATUS_MISSING_SYMBOL: status_string = tr("Missing symbol. Wrong version?") ;
|
||||
break ;
|
||||
case PLUGIN_STATUS_NULL_PLUGIN: status_string = tr("No plugin object") ;
|
||||
break ;
|
||||
case PLUGIN_STATUS_LOADED: status_string = tr("Plugins is loaded.") ;
|
||||
break ;
|
||||
case PLUGIN_STATUS_REJECTED_HASH: status_string = tr("Hash rejected. Enable it manually and restart, if you need.") ;
|
||||
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.") ;
|
||||
break ;
|
||||
|
||||
case PLUGIN_STATUS_MISSING_SYMBOL:status_string = tr("Missing symbol. Wrong version?") ;
|
||||
break ;
|
||||
|
||||
case PLUGIN_STATUS_NULL_PLUGIN: status_string = tr("No plugin object") ;
|
||||
break ;
|
||||
|
||||
case PLUGIN_STATUS_LOADED: status_string = tr("Plugins is loaded.") ;
|
||||
break ;
|
||||
default:
|
||||
status_string = tr("Unknown status.") ;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "notifytxt.h"
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <string.h>
|
||||
@ -84,6 +84,23 @@ void NotifyTxt::notifyChat()
|
||||
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)
|
||||
{
|
||||
char *passwd = getpass(("Please enter GPG password for key "+key_details+": ").c_str()) ;
|
||||
|
@ -41,6 +41,7 @@ class NotifyTxt: public NotifyBase
|
||||
virtual void notifyErrorMsg(int list, int sev, std::string msg);
|
||||
virtual void notifyChat();
|
||||
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:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user