From ab5da5ebf5198dad5e59847d6d8d736079bfb8ac Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 29 Aug 2019 23:15:46 +0200 Subject: [PATCH] switched to RsLoginHelper for login attempt in rs-service. Moved commandline arguments to main executable using a new struct named RsConfigOptions --- libresapi/src/api/RsControlModule.cpp | 3 +- libretroshare/src/retroshare/rsinit.h | 50 ++- libretroshare/src/rsserver/rsinit.cc | 333 +++++++------------ retroshare-gui/src/main.cpp | 33 +- retroshare-nogui/src/retroshare.cc | 11 +- retroshare-service/src/retroshare-service.cc | 156 +++++++-- retroshare.pri | 6 +- 7 files changed, 339 insertions(+), 253 deletions(-) diff --git a/libresapi/src/api/RsControlModule.cpp b/libresapi/src/api/RsControlModule.cpp index 5f07ed7ff..199711a63 100644 --- a/libresapi/src/api/RsControlModule.cpp +++ b/libresapi/src/api/RsControlModule.cpp @@ -145,7 +145,8 @@ void RsControlModule::run() #endif RsInit::InitRsConfig(); - int initResult = RsInit::InitRetroShare(argc, argv, true); + RsConfigOptions opt; + int initResult = RsInit::InitRetroShare(opt); if (initResult < 0) { std::cerr << "RsControlModule: FATAL ERROR, initialising libretroshare FAILED." << std::endl; diff --git a/libretroshare/src/retroshare/rsinit.h b/libretroshare/src/retroshare/rsinit.h index fc71b5ae9..a3cde9169 100644 --- a/libretroshare/src/retroshare/rsinit.h +++ b/libretroshare/src/retroshare/rsinit.h @@ -30,6 +30,7 @@ #define RS_INIT_AUTH_FAILED -1 // AuthGPG::InitAuth failed #define RS_INIT_BASE_DIR_ERROR -2 // AuthGPG::InitAuth failed #define RS_INIT_NO_KEYRING -3 // Keyring is empty. Need to import it. +#define RS_INIT_NO_EXECUTABLE -4 // executable path hasn't been set in config options #include #include @@ -45,6 +46,38 @@ struct RsLoginHelper; */ extern RsLoginHelper* rsLoginHelper; +/** + * @brief The RsInitConfig struct + * This class contains common configuration options, that executables using libretroshare may want to + * set using e.g. commandline options. To be passed to RsInit::InitRetroShare(). + */ +struct RsConfigOptions +{ + RsConfigOptions(); + + // required + + std::string main_executable_path;/* this should be set to argv[0] */ + + // Optional. Only change if needed. + + bool autoLogin; /* try auto-login */ + + bool udpListenerOnly; /* only listen to udp */ + std::string forcedInetAddress; /* inet address to use.*/ + uint16_t forcedPort; /* port to listen to */ + + bool outStderr; + int debugLevel; + std::string logfname; /* output filename for log */ + + std::string opModeStr; /* operating mode. Acceptable values: "Full", "NoTurtle", "Gaming", "Minimal" */ + std::string optBaseDir; /* base directory where to find profiles, etc */ + + uint16_t jsonApiPort; /* port to use fo Json API */ + std::string jsonApiBindAddress; /* bind address for Json API */ +}; + /*! * Initialisation Class (not publicly disclosed to RsIFace) @@ -57,7 +90,7 @@ public: OK, /// Everything go as expected, no error occurred ERR_ALREADY_RUNNING, /// Another istance is running already ERR_CANT_ACQUIRE_LOCK, /// Another istance is already running? - ERR_UNKOWN /// Unkown error, maybe password is wrong? + ERR_UNKNOWN /// Unkown error, maybe password is wrong? }; /* reorganised RsInit system */ @@ -77,12 +110,19 @@ public: * invalid argument passed and vice versa * @return RS_INIT_... */ - static int InitRetroShare(int argc, char **argv, bool strictCheck=true); + static int InitRetroShare(const RsConfigOptions&); static bool isPortable(); static bool isWindowsXP(); static bool collectEntropy(uint32_t bytes) ; + /*! + * \brief lockFilePath + * \return + * full path for the lock file. Can be used to warn the user about a non deleted lock that would prevent to start. + */ + static std::string lockFilePath(); + /* * Setup Hidden Location; */ @@ -270,8 +310,10 @@ extern RsAccounts* rsAccounts; * This helper class have been implemented because there was not reasonable way * to login in the API that could be exposed via JSON API */ -struct RsLoginHelper +class RsLoginHelper { +public: + RsLoginHelper() {} /** * @brief Normal way to attempt login * @jsonapi{development,manualwrapper} @@ -295,7 +337,7 @@ struct RsLoginHelper RsPeerId mLocationId; RsPgpId mPgpId; std::string mLocationName; - std::string mPpgName; + std::string mPgpName; /// @see RsSerializable::serial_process void serial_process( RsGenericSerializer::SerializeJob j, diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 163f10fac..a3b51238a 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -116,6 +116,19 @@ RsLoginHelper* rsLoginHelper = nullptr; RsAccounts* rsAccounts = nullptr; +RsConfigOptions::RsConfigOptions() + : jsonApiPort(JsonApiServer::DEFAULT_PORT), + jsonApiBindAddress("127.0.0.1") +{ + autoLogin = false; + forcedPort=0; + udpListenerOnly=false; + + outStderr=false; + debugLevel=5; +} + + struct RsInitConfig { RsInitConfig() : jsonApiPort(JsonApiServer::DEFAULT_PORT), jsonApiBindAddress("127.0.0.1") {} @@ -159,6 +172,7 @@ struct RsInitConfig bool udpListenerOnly; std::string opModeStr; + std::string optBaseDir; uint16_t jsonApiPort; std::string jsonApiBindAddress; @@ -266,229 +280,111 @@ bool doPortRestrictions = false; * #define LOCALNET_TESTING 1 * ********/ -int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */) +int RsInit::InitRetroShare(const RsConfigOptions& conf) { -#ifdef DEBUG_RSINIT - for(int i=0; iautoLogin = conf.autoLogin; + rsInitConfig->outStderr = conf.outStderr; + rsInitConfig->logfname = conf.logfname ; + rsInitConfig->inet = conf.forcedInetAddress ; + rsInitConfig->port = conf.forcedPort ; + rsInitConfig->debugLevel = conf.debugLevel; + rsInitConfig->optBaseDir = conf.optBaseDir; + rsInitConfig->jsonApiPort = conf.jsonApiPort; + rsInitConfig->jsonApiBindAddress = conf.jsonApiBindAddress; #ifdef PTW32_STATIC_LIB // for static PThreads under windows... we need to init the library... pthread_win32_process_attach_np(); #endif - - std::string prefUserString = ""; - std::string opt_base_dir; - -#ifdef __APPLE__ - // TODO: is this still needed with argstream? - /* HACK to avoid stupid OSX Finder behaviour - * remove the commandline arguments - if we detect we are launched from Finder, - * and we have the unparsable "-psn_0_12332" option. - * this is okay, as you cannot pass commandline arguments via Finder anyway - */ - if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4))) argc = 1; + if( rsInitConfig->autoLogin) rsInitConfig->startMinimised = true ; + if( rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ; + if(!rsInitConfig->logfname.empty()) rsInitConfig->haveLogFile = true; + if( rsInitConfig->inet != "127.0.0.1") rsInitConfig->forceLocalAddr = true; + if( rsInitConfig->port != 0) rsInitConfig->forceExtPort = true; +#ifdef LOCALNET_TESTING + if(!portRestrictions.empty()) doPortRestrictions = true; #endif + setOutputLevel((RsLog::logLvl)rsInitConfig->debugLevel); - argstream as(argc,argv); - as >> option('s',"stderr" ,rsInitConfig->outStderr ,"output to stderr instead of log file." ) - >> option('u',"udp" ,rsInitConfig->udpListenerOnly,"Only listen to UDP." ) - >> option('e',"external-port" ,rsInitConfig->forceExtPort ,"Use a forwarded external port." ) - >> parameter('c',"base-dir" ,opt_base_dir ,"directory", "Set base directory." ,false) - >> parameter('l',"log-file" ,rsInitConfig->logfname ,"logfile" ,"Set Log filename." ,false) - >> parameter('d',"debug-level" ,rsInitConfig->debugLevel ,"level" ,"Set debug level." ,false) - >> parameter('i',"ip-address" ,rsInitConfig->inet ,"nnn.nnn.nnn.nnn", "Force IP address to use (if cannot be detected)." ,false) - >> parameter('o',"opmode" ,rsInitConfig->opModeStr ,"opmode" ,"Set Operating mode (Full, NoTurtle, Gaming, Minimal)." ,false) - >> parameter('p',"port" ,rsInitConfig->port ,"port", "Set listenning port to use." ,false) - >> parameter('U',"user-id" ,prefUserString ,"ID", "[ocation Id] Selected account to use and asks for passphrase. Use \"-u list\" in order to list available accounts.",false); + // set the debug file. + if (rsInitConfig->haveLogFile) + setDebugFile(rsInitConfig->logfname.c_str()); -#ifdef RS_JSONAPI - as >> parameter('J', "jsonApiPort", rsInitConfig->jsonApiPort, "jsonApiPort", "Enable JSON API on the specified port", false ) - >> parameter('P', "jsonApiBindAddress", rsInitConfig->jsonApiBindAddress, "jsonApiBindAddress", "JSON API Bind Address.", false); -#endif // ifdef RS_JSONAPI - -#ifdef LOCALNET_TESTING - as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false); -#endif // ifdef LOCALNET_TESTING - -#ifdef RS_AUTOLOGIN - as >> option('a',"auto-login" ,rsInitConfig->autoLogin ,"AutoLogin (Windows Only) + StartMinimised"); -#endif // ifdef RS_AUTOLOGIN - - as >> help('h',"help","Display this Help"); - as.defaultErrorHandling(true,true); - - - if(rsInitConfig->autoLogin) rsInitConfig->startMinimised = true ; - if(rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ; - if(!rsInitConfig->logfname.empty()) rsInitConfig->haveLogFile = true; - if(rsInitConfig->inet != "127.0.0.1") rsInitConfig->forceLocalAddr = true; -#ifdef LOCALNET_TESTING - if(!portRestrictions.empty()) doPortRestrictions = true; -#endif - - setOutputLevel((RsLog::logLvl)rsInitConfig->debugLevel); - - // set the debug file. - if (rsInitConfig->haveLogFile) - setDebugFile(rsInitConfig->logfname.c_str()); - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ #else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } #endif - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // SWITCH off the SIGPIPE - kills process on Linux. - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + // SWITCH off the SIGPIPE - kills process on Linux. + /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS - struct sigaction sigact; - sigact.sa_handler = SIG_IGN; - sigact.sa_flags = 0; + struct sigaction sigact; + sigact.sa_handler = SIG_IGN; + sigact.sa_flags = 0; - sigset_t set; - sigemptyset(&set); - //sigaddset(&set, SIGINT); // or whatever other signal - sigact.sa_mask = set; + sigset_t set; + sigemptyset(&set); + //sigaddset(&set, SIGINT); // or whatever other signal + sigact.sa_mask = set; - if (0 == sigaction(SIGPIPE, &sigact, NULL)) - { - std::cerr << "RetroShare:: Successfully installed the SIGPIPE Block" << std::endl; - } - else - { - std::cerr << "RetroShare:: Failed to install the SIGPIPE Block" << std::endl; - } + if (0 == sigaction(SIGPIPE, &sigact, NULL)) + { + std::cerr << "RetroShare:: Successfully installed the SIGPIPE Block" << std::endl; + } + else + { + std::cerr << "RetroShare:: Failed to install the SIGPIPE Block" << std::endl; + } #endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // Hash the main executable. + // Hash the main executable. - uint64_t tmp_size ; + uint64_t tmp_size ; - 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; + if(conf.main_executable_path.empty()) + { + std::cerr << "Executable path is unknown. It should normally have been set in passed RsConfigOptions structure" << std::endl; + return 1; + } + if(!RsDirUtil::getFileHash(conf.main_executable_path,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. * 3) Get Prefered Id. * 2) Get List of Available Accounts. * 4) Get List of GPG Accounts. */ - /* Initialize AuthSSL */ - AuthSSL::instance().InitAuth(nullptr, nullptr, nullptr, ""); + /* Initialize AuthSSL */ + AuthSSL::instance().InitAuth(nullptr, nullptr, nullptr, ""); - rsLoginHelper = new RsLoginHelper; + rsLoginHelper = new RsLoginHelper; - int error_code ; + int error_code ; - if(!RsAccounts::init(opt_base_dir,error_code)) - return error_code ; + if(!RsAccounts::init(rsInitConfig->optBaseDir,error_code)) + return error_code ; - // choose alternative account. - if(prefUserString != "") - { - if(prefUserString == "list") - { - std::cerr << "Available accounts:" << std::endl; - - std::list account_ids; - RsAccounts::GetAccountIds(account_ids); - - int account_number_size = (int)ceil(log(account_ids.size())/log(10.0f)) ; - int i=1; - - for(auto it(account_ids.begin());it!=account_ids.end();++it,++i) - { - RsPgpId pgp_id; - std::string pgp_name; - std::string loc_name; - std::string pgp_email; - - RsAccounts::GetAccountDetails(*it,pgp_id,pgp_name,pgp_email,loc_name); - - std::cout << "[" << std::setw(account_number_size) << std::setfill('0') - << i << "] " << *it << " (" << pgp_id << "): " << pgp_name << " \t (" << loc_name << ")" << std::endl; - } - int nacc=0; - - while(nacc < 1 || nacc >= account_ids.size()) - { - std::cout << "Please enter account number: "; - std::cout.flush(); - std::string str; - std::getline(std::cin, str); - - nacc = atoi(str.c_str()); - - i=1; - for(auto it(account_ids.begin());it!=account_ids.end();++it,++i) - if(i==nacc) - { - prefUserString = (*it).toStdString(); - break; - } - nacc=0; // allow to continue if something goes wrong. - - - RsPeerId ssl_id(prefUserString); - - if(ssl_id.isNull()) - { - std::cerr << "Invalid User location id: not found in list"; - std::cerr << std::endl; - continue; - } - - if(!RsAccounts::SelectAccount(ssl_id)) - continue; - - if(!RsLoginHandler::getSSLPassword(ssl_id,true,rsInitConfig->passwd)) - { - std::cerr << "No valid password supplied for this account." << std::endl; - continue; - } - - std::string lockFile; - int retVal = RsInit::LockAndLoadCertificates(false, lockFile); - - switch (retVal) - { - case 0: break; - case 1: std::cerr << "Another RetroShare using the same profile is already running on your system. Please close " - "that instance first\n Lock file:\n" << lockFile << std::endl; - continue; - case 2: std::cerr << "An unexpected error occurred when Retroshare tried to acquire the single instance lock\n Lock file:\n" - << lockFile.c_str() << std::endl; - continue; - case 3: - default: std::cerr << "Rshare::loadCertificate() unexpected switch value " << retVal << std::endl; - continue; - } - RsControl::instance()->StartupRetroShare(); - break; - } - } - - } #ifdef RS_AUTOLOGIN /* check that we have selected someone */ @@ -509,9 +405,7 @@ int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */) #ifdef RS_JSONAPI if(rsInitConfig->jsonApiPort) { - jsonApiServer = new JsonApiServer( - rsInitConfig->jsonApiPort, - rsInitConfig->jsonApiBindAddress ); + jsonApiServer = new JsonApiServer( rsInitConfig->jsonApiPort, rsInitConfig->jsonApiBindAddress ); jsonApiServer->start("JSON API Server"); } #endif // ifdef RS_JSONAPI @@ -543,7 +437,7 @@ RsInit::LoadCertificateStatus RsInit::LockConfigDirectory( case 0: return RsInit::OK; case 1: return RsInit::ERR_ALREADY_RUNNING; case 2: return RsInit::ERR_CANT_ACQUIRE_LOCK; - default: return RsInit::ERR_UNKOWN; + default: return RsInit::ERR_UNKNOWN; } } @@ -576,27 +470,32 @@ bool RsInit::LoadPassword(const std::string& inPwd) return true; } +std::string RsInit::lockFilePath() +{ + return RsAccounts::AccountDirectory() + "/lock" ; +} + RsInit::LoadCertificateStatus RsInit::LockAndLoadCertificates( bool autoLoginNT, std::string& lockFilePath ) { try { if (!RsAccounts::lockPreferredAccount()) - throw RsInit::ERR_UNKOWN; // invalid PreferredAccount. + throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount. // Logic that used to be external to RsInit... RsPeerId accountId; if (!RsAccounts::GetPreferredAccountId(accountId)) - throw RsInit::ERR_UNKOWN; // invalid PreferredAccount; + throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount; RsPgpId pgpId; std::string pgpName, pgpEmail, location; if(!RsAccounts::GetAccountDetails(accountId, pgpId, pgpName, pgpEmail, location)) - throw RsInit::ERR_UNKOWN; // invalid PreferredAccount; + throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount; if(0 == AuthGPG::getAuthGPG() -> GPGInit(pgpId)) - throw RsInit::ERR_UNKOWN; // PGP Error. + throw RsInit::ERR_UNKNOWN; // PGP Error. LoadCertificateStatus retVal = LockConfigDirectory(RsAccounts::AccountDirectory(), lockFilePath); @@ -607,7 +506,7 @@ RsInit::LoadCertificateStatus RsInit::LockAndLoadCertificates( if(LoadCertificates(autoLoginNT) != 1) { UnlockConfigDirectory(); - throw RsInit::ERR_UNKOWN; + throw RsInit::ERR_UNKNOWN; } return RsInit::OK; @@ -1276,7 +1175,8 @@ int RsServer::StartupRetroShare() plugins_directories.push_back(extensions_dir) ; if(!RsDirUtil::checkCreateDirectory(extensions_dir)) - std::cerr << "(EE) Cannot create extensions directory " + extensions_dir + ". This is not mandatory, but you probably have a permission problem." << std::endl; + std::cerr << "(EE) Cannot create extensions directory " << extensions_dir + << ". This is not mandatory, but you probably have a permission problem." << std::endl; #ifdef DEBUG_PLUGIN_SYSTEM plugins_directories.push_back(".") ; // this list should be saved/set to some correct value. @@ -1975,21 +1875,24 @@ int RsServer::StartupRetroShare() return 1; } -RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin( - const RsPeerId& account, const std::string& password) +RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(const RsPeerId& account, const std::string& password) { if(isLoggedIn()) return RsInit::ERR_ALREADY_RUNNING; - if(!rsNotify->cachePgpPassphrase(password)) return RsInit::ERR_UNKOWN; - if(!rsNotify->setDisableAskPassword(true)) return RsInit::ERR_UNKOWN; - if(!RsAccounts::SelectAccount(account)) return RsInit::ERR_UNKOWN; + + if(!password.empty()) + { + if(!rsNotify->cachePgpPassphrase(password)) return RsInit::ERR_UNKNOWN; + if(!rsNotify->setDisableAskPassword(true)) return RsInit::ERR_UNKNOWN; + } + if(!RsAccounts::SelectAccount(account)) return RsInit::ERR_UNKNOWN; std::string _ignore_lockFilePath; - RsInit::LoadCertificateStatus ret = - RsInit::LockAndLoadCertificates(false, _ignore_lockFilePath); - if(!rsNotify->setDisableAskPassword(false)) return RsInit::ERR_UNKOWN; - if(!rsNotify->clearPgpPassphrase()) return RsInit::ERR_UNKOWN; + RsInit::LoadCertificateStatus ret = RsInit::LockAndLoadCertificates(false, _ignore_lockFilePath); + + if(!rsNotify->setDisableAskPassword(false)) return RsInit::ERR_UNKNOWN; + if(!rsNotify->clearPgpPassphrase()) return RsInit::ERR_UNKNOWN; if(ret != RsInit::OK) return ret; if(RsControl::instance()->StartupRetroShare() == 1) return RsInit::OK; - return RsInit::ERR_UNKOWN; + return RsInit::ERR_UNKNOWN; } /*static*/ bool RsLoginHelper::collectEntropy(uint32_t bytes) @@ -2005,7 +1908,7 @@ void RsLoginHelper::getLocations(std::vector& store) { Location l; l.mLocationId = locId; std::string discardPgpMail; - RsAccounts::GetAccountDetails( locId, l.mPgpId, l.mPpgName, + RsAccounts::GetAccountDetails( locId, l.mPgpId, l.mPgpName, discardPgpMail, l.mLocationName ); store.push_back(l); } @@ -2023,14 +1926,14 @@ bool RsLoginHelper::createLocation( return false; } - if(l.mPgpId.isNull() && l.mPpgName.empty()) + if(l.mPgpId.isNull() && l.mPgpName.empty()) { errorMessage = "Either PGP name or PGP id is needed"; return false; } if(l.mPgpId.isNull() && !RsAccounts::GeneratePGPCertificate( - l.mPpgName, "", password, l.mPgpId, 4096, errorMessage) ) + l.mPgpName, "", password, l.mPgpId, 4096, errorMessage) ) { errorMessage = "Failure creating PGP key: " + errorMessage; return false; @@ -2065,7 +1968,7 @@ void RsLoginHelper::Location::serial_process( RS_SERIAL_PROCESS(mLocationId); RS_SERIAL_PROCESS(mPgpId); RS_SERIAL_PROCESS(mLocationName); - RS_SERIAL_PROCESS(mPpgName); + RS_SERIAL_PROCESS(mPgpName); } /*static*/ bool RsAccounts::getCurrentAccountId(RsPeerId& id) diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index 33387c68a..87b57f79f 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -21,6 +21,7 @@ *******************************************************************************/ #include "util/stacktrace.h" +#include "util/argstream.h" CrashStackTrace gCrashStackTrace; @@ -50,6 +51,7 @@ CrashStackTrace gCrashStackTrace; #include "util/RsGxsUpdateBroadcast.h" #include "util/rsdir.h" #include "util/rstime.h" +#include "retroshare/rsinit.h" #ifdef MESSENGER_WINDOW #include "gui/MessengerWindow.h" @@ -228,7 +230,34 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); /* RetroShare Core Objects */ RsInit::InitRsConfig(); - int initResult = RsInit::InitRetroShare(argc, argv); + + RsConfigOptions conf; + + argstream as(argc,argv); + as >> option('s',"stderr" ,conf.outStderr ,"output to stderr instead of log file." ) + >> option('u',"udp" ,conf.udpListenerOnly,"Only listen to UDP." ) + >> parameter('c',"base-dir" ,conf.optBaseDir ,"directory", "Set base directory." ,false) + >> parameter('l',"log-file" ,conf.logfname ,"logfile" ,"Set Log filename." ,false) + >> parameter('d',"debug-level" ,conf.debugLevel ,"level" ,"Set debug level." ,false) + >> parameter('i',"ip-address" ,conf.forcedInetAddress,"nnn.nnn.nnn.nnn", "Force IP address to use (if cannot be detected)." ,false) + >> parameter('p',"port" ,conf.forcedPort ,"port" ,"Set listenning port to use." ,false) + >> parameter('o',"opmode" ,conf.opModeStr ,"opmode" ,"Set Operating mode (Full, NoTurtle, Gaming, Minimal)." ,false); +#ifdef RS_JSONAPI + as >> parameter('J', "jsonApiPort", conf.jsonApiPort, "jsonApiPort", "Enable JSON API on the specified port", false ) + >> parameter('P', "jsonApiBindAddress", conf.jsonApiBindAddress, "jsonApiBindAddress", "JSON API Bind Address.", false); +#endif // ifdef RS_JSONAPI + +#ifdef LOCALNET_TESTING + as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false); +#endif // ifdef LOCALNET_TESTING + +#ifdef RS_AUTOLOGIN + as >> option('a',"auto-login" ,conf.autoLogin ,"AutoLogin (Windows Only) + StartMinimised"); +#endif // ifdef RS_AUTOLOGIN + + conf.main_executable_path = argv[0]; + + int initResult = RsInit::InitRetroShare(conf); if(initResult == RS_INIT_NO_KEYRING) // happens when we already have accounts, but no pgp key. This is when switching to the openpgp-sdk version. { @@ -252,7 +281,7 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); if(!RsAccounts::CopyGnuPGKeyrings()) return 0 ; - initResult = RsInit::InitRetroShare(argc, argv); + initResult = RsInit::InitRetroShare(conf); displayWarningAboutDSAKeys() ; diff --git a/retroshare-nogui/src/retroshare.cc b/retroshare-nogui/src/retroshare.cc index 7a88e72d1..1e90edd7d 100644 --- a/retroshare-nogui/src/retroshare.cc +++ b/retroshare-nogui/src/retroshare.cc @@ -57,8 +57,10 @@ int main(int argc, char **argv) { -#ifdef ENABLE_WEBUI + RsConfigOptions conf; + conf.main_executable_path = argv[0]; +#ifdef ENABLE_WEBUI std::string docroot = resource_api::getDefaultDocroot(); uint16_t httpPort = 0; std::string listenAddress; @@ -77,8 +79,9 @@ int main(int argc, char **argv) std::cerr << args.usage() << std::endl; // print libretroshare command line args and exit RsInit::InitRsConfig(); - RsInit::InitRetroShare(argc, argv, true); - return 0; + + RsInit::InitRetroShare(conf); + return 0; } resource_api::ApiServer api; @@ -126,7 +129,7 @@ int main(int argc, char **argv) bool strictCheck = true; RsInit::InitRsConfig(); - int initResult = RsInit::InitRetroShare(argc, argv, strictCheck); + int initResult = RsInit::InitRetroShare(conf); if (initResult < 0) { /* Error occured */ diff --git a/retroshare-service/src/retroshare-service.cc b/retroshare-service/src/retroshare-service.cc index c845ba3fd..a02201742 100644 --- a/retroshare-service/src/retroshare-service.cc +++ b/retroshare-service/src/retroshare-service.cc @@ -17,10 +17,13 @@ */ #include "util/stacktrace.h" +#include "util/argstream.h" +#include "retroshare/rsinit.h" #include "jsonapi/jsonapi.h" CrashStackTrace gCrashStackTrace; +#include #include #ifndef __ANDROID__ @@ -126,41 +129,146 @@ int main(int argc, char* argv[]) RsInit::InitRsConfig(); RsControl::earlyInitNotificationSystem(); +#ifndef __ANDROID__ + std::string webui_pass1 = "Y"; + std::string webui_pass2 = "N"; + + for(;;) + { + webui_pass1 = readStringFromKeyboard("Please register a password for the web interface: "); + webui_pass2 = readStringFromKeyboard("Please enter the same password again : "); + + if(webui_pass1 != webui_pass2) + { + std::cerr << "Passwords do not match!" << std::endl; + continue; + } + if(webui_pass1.empty()) + { + std::cerr << "Password cannot be empty!" << std::endl; + continue; + } + + break; + } +#endif + +#ifdef __APPLE__ + // TODO: is this still needed with argstream? + /* HACK to avoid stupid OSX Finder behaviour + * remove the commandline arguments - if we detect we are launched from Finder, + * and we have the unparsable "-psn_0_12332" option. + * this is okay, as you cannot pass commandline arguments via Finder anyway + */ + if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4))) argc = 1; +#endif + + std::string prefUserString; + RsConfigOptions conf; + + argstream as(argc,argv); + as >> option('s',"stderr" ,conf.outStderr ,"output to stderr instead of log file." ) + >> option('u',"udp" ,conf.udpListenerOnly ,"Only listen to UDP." ) + >> parameter('c',"base-dir" ,conf.optBaseDir ,"directory", "Set base directory." ,false) + >> parameter('l',"log-file" ,conf.logfname ,"logfile" ,"Set Log filename." ,false) + >> parameter('d',"debug-level" ,conf.debugLevel ,"level" ,"Set debug level." ,false) + >> parameter('i',"ip-address" ,conf.forcedInetAddress,"nnn.nnn.nnn.nnn", "Force IP address to use (if cannot be detected)." ,false) + >> parameter('o',"opmode" ,conf.opModeStr ,"opmode" ,"Set Operating mode (Full, NoTurtle, Gaming, Minimal)." ,false) + >> parameter('p',"port" ,conf.forcedPort ,"port", "Set listenning port to use." ,false) + >> parameter('U',"user-id" ,prefUserString ,"ID", "[ocation Id] Selected account to use and asks for passphrase. Use \"-u list\" in order to list available accounts.",false); + +#ifdef RS_JSONAPI + as >> parameter('J', "jsonApiPort", conf.jsonApiPort, "jsonApiPort", "Enable JSON API on the specified port", false ) + >> parameter('P', "jsonApiBindAddress", conf.jsonApiBindAddress, "jsonApiBindAddress", "JSON API Bind Address.", false); +#endif // ifdef RS_JSONAPI + +#ifdef LOCALNET_TESTING + as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false); +#endif // ifdef LOCALNET_TESTING + +#ifdef RS_AUTOLOGIN + as >> option('a',"auto-login" ,conf.autoLogin ,"AutoLogin (Windows Only) + StartMinimised"); +#endif // ifdef RS_AUTOLOGIN + + as >> help('h',"help","Display this Help"); + as.defaultErrorHandling(true,true); + #ifndef __ANDROID__ RsServiceNotify *notify = new RsServiceNotify(); rsNotify->registerNotifyClient(notify); #endif -#ifndef __ANDROID__ - std::string webui_pass1 = "Y"; - std::string webui_pass2 = "N"; + conf.main_executable_path = argv[0]; - for(;;) - { - webui_pass1 = readStringFromKeyboard("Please register a password for the web interface: "); - webui_pass2 = readStringFromKeyboard("Please enter the same password again : "); - - if(webui_pass1 != webui_pass2) - { - std::cerr << "Passwords do not match!" << std::endl; - continue; - } - if(webui_pass1.empty()) - { - std::cerr << "Password cannot be empty!" << std::endl; - continue; - } - - break; - } -#endif - - if(RsInit::InitRetroShare(argc, argv, true)) + if(RS_INIT_OK != RsInit::InitRetroShare(conf)) { std::cerr << "Could not properly init Retroshare core." << std::endl; return 1; } + // choose alternative account. + if(prefUserString != "") + { + if(prefUserString == "list") + { + std::cerr << "Available accounts:" << std::endl; + + std::vector locations; + rsLoginHelper->getLocations(locations); + + int account_number_size = (int)ceil(log(locations.size())/log(10.0f)) ; + + for(uint32_t i=0;i= locations.size()) + { + std::cout << "Please enter account number: "; + std::cout.flush(); + std::string str; + std::getline(std::cin, str); + + nacc = atoi(str.c_str())-1; + + if(nacc >= 0 && nacc < locations.size()) + { + prefUserString = locations[nacc].mLocationId.toStdString(); + break; + } + nacc=0; // allow to continue if something goes wrong. + } + } + + RsPeerId ssl_id(prefUserString); + + if(ssl_id.isNull()) + { + std::cerr << "Invalid User location id: a hexadecimal ID is expected." << std::endl; + return 1; + } + + RsInit::LoadCertificateStatus result = rsLoginHelper->attemptLogin(ssl_id,std::string()); // supply empty passwd so that it is properly asked 3 times on console + + std::string lock_file_path = RsAccounts::AccountDirectory()+"/lock" ; + + switch(result) + { + case RsInit::OK: break; + case RsInit::ERR_ALREADY_RUNNING: std::cerr << "Another RetroShare using the same profile is already running on your system. Please close " + "that instance first.\nLock file: " << RsInit::lockFilePath() << std::endl; + return 1; + case RsInit::ERR_CANT_ACQUIRE_LOCK: std::cerr << "An unexpected error occurred when Retroshare tried to acquire the single instance lock file. \nLock file: " << RsInit::lockFilePath() << std::endl; + return 1; + case RsInit::ERR_UNKNOWN: + default: std::cerr << "Unknown error." << std::endl; + return 1; + } + } + #ifdef __ANDROID__ rsControl->setShutdownCallback(QCoreApplication::exit); diff --git a/retroshare.pri b/retroshare.pri index 6a74c94d5..9833447ff 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -33,8 +33,8 @@ CONFIG *= gxsdistsync # To disable RetroShare-nogui append the following # assignation to qmake command line "CONFIG+=no_retroshare_nogui" -CONFIG *= retroshare_nogui -no_retroshare_nogui:CONFIG -= retroshare_nogui +CONFIG *= no_retroshare_nogui +retroshare_nogui:CONFIG -= no_retroshare_nogui # To disable cmark append the following # assignation to qmake command line "CONFIG+=no_cmark" @@ -64,7 +64,7 @@ retroshare_qml_app:CONFIG -= no_retroshare_qml_app # To enable RetroShare service append the following assignation to # qmake command line "CONFIG+=retroshare_service" -CONFIG *= no_retroshare_service +CONFIG *= retroshare_service retroshare_service:CONFIG -= no_retroshare_service # To disable libresapi append the following assignation to qmake command line