Merge pull request #1345 from p12tic/filesystem-cleanup
Filesystem operations cleanup
This commit is contained in:
commit
6d7eca42b7
|
@ -4,3 +4,6 @@
|
|||
[submodule "ext/gmock"]
|
||||
path = ext/gmock
|
||||
url = https://github.com/google/googlemock.git
|
||||
[submodule "ext/gulrak-filesystem"]
|
||||
path = ext/gulrak-filesystem
|
||||
url = https://github.com/gulrak/filesystem
|
||||
|
|
|
@ -301,6 +301,8 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
|||
)
|
||||
endif()
|
||||
|
||||
include_directories("${CMAKE_SOURCE_DIR}/ext/gulrak-filesystem/include")
|
||||
|
||||
#
|
||||
# OpenSSL
|
||||
#
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 614bbe87b80435d87ab8791564370e0c1d13627d
|
|
@ -442,7 +442,7 @@ void MainWindow::checkFingerprint(const QString& line)
|
|||
barrier::string::from_hex(fingerprintRegex.cap(2).toStdString())
|
||||
};
|
||||
|
||||
auto db_path = DataDirectories::trusted_servers_ssl_fingerprints_path();
|
||||
auto db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path();
|
||||
|
||||
// We compare only SHA256 fingerprints, but show both SHA1 and SHA256 so that the users can
|
||||
// still verify fingerprints on old Barrier servers. This way the only time when we are exposed
|
||||
|
@ -564,7 +564,7 @@ void MainWindow::startBarrier()
|
|||
// launched the process (e.g. when launched with elevation). setting the
|
||||
// profile dir on launch ensures it uses the same profile dir is used
|
||||
// no matter how its relaunched.
|
||||
args << "--profile-dir" << QString::fromStdString("\"" + DataDirectories::profile() + "\"");
|
||||
args << "--profile-dir" << QString::fromStdString("\"" + barrier::DataDirectories::profile().u8string() + "\"");
|
||||
#endif
|
||||
|
||||
if ((barrierType() == barrierClient && !clientArgs(args, app))
|
||||
|
@ -1020,8 +1020,8 @@ void MainWindow::updateSSLFingerprint()
|
|||
return;
|
||||
}
|
||||
|
||||
auto local_path = DataDirectories::local_ssl_fingerprints_path();
|
||||
if (!QFile::exists(QString::fromStdString(local_path))) {
|
||||
auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path();
|
||||
if (!barrier::fs::exists(local_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,45 +18,36 @@
|
|||
#include "SslCertificate.h"
|
||||
#include "common/DataDirectories.h"
|
||||
#include "base/finally.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
#include "net/FingerprintDatabase.h"
|
||||
#include "net/SecureUtils.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
static const char kCertificateFilename[] = "Barrier.pem";
|
||||
static const char kSslDir[] = "SSL";
|
||||
|
||||
SslCertificate::SslCertificate(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_ProfileDir = DataDirectories::profile();
|
||||
if (m_ProfileDir.empty()) {
|
||||
if (barrier::DataDirectories::profile().empty()) {
|
||||
emit error(tr("Failed to get profile directory."));
|
||||
}
|
||||
}
|
||||
|
||||
void SslCertificate::generateCertificate()
|
||||
{
|
||||
auto cert_path = getCertificatePath();
|
||||
auto cert_path = barrier::DataDirectories::ssl_certificate_path();
|
||||
|
||||
QFile file(QString::fromStdString(cert_path));
|
||||
if (!file.exists() || !isCertificateValid(cert_path)) {
|
||||
QDir sslDir(QString::fromStdString(getCertificateDirectory()));
|
||||
if (!sslDir.exists()) {
|
||||
sslDir.mkpath(".");
|
||||
if (!barrier::fs::exists(cert_path) || !is_certificate_valid(cert_path)) {
|
||||
try {
|
||||
auto cert_dir = cert_path.parent_path();
|
||||
if (!barrier::fs::exists(cert_dir)) {
|
||||
barrier::fs::create_directories(cert_dir);
|
||||
}
|
||||
|
||||
try {
|
||||
barrier::generate_pem_self_signed_cert(cert_path);
|
||||
barrier::generate_pem_self_signed_cert(cert_path.u8string());
|
||||
} catch (const std::exception& e) {
|
||||
emit error(QString("SSL tool failed: %1").arg(e.what()));
|
||||
return;
|
||||
|
@ -65,19 +56,19 @@ void SslCertificate::generateCertificate()
|
|||
emit info(tr("SSL certificate generated."));
|
||||
}
|
||||
|
||||
generateFingerprint(cert_path);
|
||||
generate_fingerprint(cert_path);
|
||||
|
||||
emit generateFinished();
|
||||
}
|
||||
|
||||
void SslCertificate::generateFingerprint(const std::string& cert_path)
|
||||
void SslCertificate::generate_fingerprint(const barrier::fs::path& cert_path)
|
||||
{
|
||||
try {
|
||||
auto local_path = DataDirectories::local_ssl_fingerprints_path();
|
||||
auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path();
|
||||
barrier::FingerprintDatabase db;
|
||||
db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path,
|
||||
db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(),
|
||||
barrier::FingerprintType::SHA1));
|
||||
db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path,
|
||||
db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(),
|
||||
barrier::FingerprintType::SHA256));
|
||||
db.write(local_path);
|
||||
|
||||
|
@ -87,17 +78,7 @@ void SslCertificate::generateFingerprint(const std::string& cert_path)
|
|||
}
|
||||
}
|
||||
|
||||
std::string SslCertificate::getCertificatePath()
|
||||
{
|
||||
return getCertificateDirectory() + QDir::separator().toLatin1() + kCertificateFilename;
|
||||
}
|
||||
|
||||
std::string SslCertificate::getCertificateDirectory()
|
||||
{
|
||||
return m_ProfileDir + QDir::separator().toLatin1() + kSslDir;
|
||||
}
|
||||
|
||||
bool SslCertificate::isCertificateValid(const std::string& path)
|
||||
bool SslCertificate::is_certificate_valid(const barrier::fs::path& path)
|
||||
{
|
||||
OpenSSL_add_all_algorithms();
|
||||
ERR_load_crypto_strings();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <string>
|
||||
#include "io/filesystem.h"
|
||||
|
||||
class SslCertificate : public QObject
|
||||
{
|
||||
|
@ -36,13 +37,7 @@ signals:
|
|||
void generateFinished();
|
||||
|
||||
private:
|
||||
std::pair<bool, std::string> runTool(const QStringList& args);
|
||||
void generateFingerprint(const std::string& cert_path);
|
||||
void generate_fingerprint(const barrier::fs::path& cert_path);
|
||||
|
||||
std::string getCertificatePath();
|
||||
std::string getCertificateDirectory();
|
||||
|
||||
bool isCertificateValid(const std::string& path);
|
||||
private:
|
||||
std::string m_ProfileDir;
|
||||
bool is_certificate_valid(const barrier::fs::path& path);
|
||||
};
|
||||
|
|
|
@ -164,7 +164,7 @@ App::initApp(int argc, const char** argv)
|
|||
// parse command line
|
||||
parseArgs(argc, argv);
|
||||
|
||||
DataDirectories::profile(argsBase().m_profileDirectory);
|
||||
barrier::DataDirectories::profile(argsBase().m_profileDirectory);
|
||||
|
||||
// set log filter
|
||||
if (!CLOG->setFilter(argsBase().m_logFilter)) {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "barrier/ArgsBase.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/String.h"
|
||||
#include "common/PathUtilities.h"
|
||||
#include "io/filesystem.h"
|
||||
|
||||
#ifdef WINAPI_MSWINDOWS
|
||||
#include <VersionHelpers.h>
|
||||
|
@ -288,10 +288,10 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i)
|
|||
argsBase().m_enableCrypto = false;
|
||||
}
|
||||
else if (isArg(i, argc, argv, NULL, "--profile-dir", 1)) {
|
||||
argsBase().m_profileDirectory = argv[++i];
|
||||
argsBase().m_profileDirectory = barrier::fs::u8path(argv[++i]);
|
||||
}
|
||||
else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) {
|
||||
argsBase().m_pluginDirectory = argv[++i];
|
||||
argsBase().m_pluginDirectory = barrier::fs::u8path(argv[++i]);
|
||||
}
|
||||
else {
|
||||
// option not supported here
|
||||
|
@ -487,7 +487,13 @@ void
|
|||
ArgParser::updateCommonArgs(const char* const* argv)
|
||||
{
|
||||
argsBase().m_name = ARCH->getHostName();
|
||||
argsBase().m_exename = PathUtilities::basename(argv[0]);
|
||||
argsBase().m_exename = parse_exename(argv[0]);
|
||||
}
|
||||
|
||||
std::string ArgParser::parse_exename(const char* arg)
|
||||
{
|
||||
// FIXME: we assume UTF-8 encoding, but on Windows this is not correct
|
||||
return barrier::fs::u8path(arg).filename().u8string();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -48,11 +48,14 @@ public:
|
|||
static String assembleCommand(std::vector<String>& argsArray,
|
||||
String ignoreArg = "", int parametersRequired = 0);
|
||||
|
||||
static std::string parse_exename(const char* arg);
|
||||
|
||||
private:
|
||||
void updateCommonArgs(const char* const* argv);
|
||||
bool checkUnexpectedArgs();
|
||||
|
||||
static ArgsBase& argsBase() { return *m_argsBase; }
|
||||
|
||||
bool parseMSWindowsArg(ArgsBase& argsBase, const int& argc, const char* const* argv, int& i);
|
||||
bool parseCarbonArg(ArgsBase& argsBase, const int& argc, const char* const* argv, int& i);
|
||||
bool parseXWindowsArg(ArgsBase& argsBase, const int& argc, const char* const* argv, int& i);
|
||||
|
|
|
@ -43,7 +43,7 @@ m_dropTarget(""),
|
|||
m_shouldExit(false),
|
||||
m_barrierAddress(),
|
||||
m_enableCrypto(true),
|
||||
m_profileDirectory(""),
|
||||
m_profileDirectory(),
|
||||
m_pluginDirectory("")
|
||||
{
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/String.h"
|
||||
#include "io/filesystem.h"
|
||||
|
||||
class ArgsBase {
|
||||
public:
|
||||
|
@ -50,6 +51,6 @@ public:
|
|||
bool m_shouldExit;
|
||||
String m_barrierAddress;
|
||||
bool m_enableCrypto;
|
||||
String m_profileDirectory;
|
||||
String m_pluginDirectory;
|
||||
barrier::fs::path m_profileDirectory;
|
||||
barrier::fs::path m_pluginDirectory;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "base/TMethodJob.h"
|
||||
#include "base/Log.h"
|
||||
#include "common/Version.h"
|
||||
#include "common/PathUtilities.h"
|
||||
|
||||
#if WINAPI_MSWINDOWS
|
||||
#include "platform/MSWindowsScreen.h"
|
||||
|
@ -522,7 +521,7 @@ ClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc
|
|||
{
|
||||
// general initialization
|
||||
m_serverAddress = new NetworkAddress;
|
||||
args().m_exename = PathUtilities::basename(argv[0]);
|
||||
argsBase().m_exename = ArgParser::parse_exename(argv[0]);
|
||||
|
||||
// install caller's output filter
|
||||
if (outputter != NULL) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "barrier/DropHelper.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "base/TMethodEventJob.h"
|
||||
#include "common/Version.h"
|
||||
#include "common/DataDirectories.h"
|
||||
#include "common/PathUtilities.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
|
@ -129,11 +128,15 @@ ServerApp::help()
|
|||
#endif
|
||||
|
||||
// refer to custom profile directory even if not saved yet
|
||||
String profilePath = argsBase().m_profileDirectory;
|
||||
if (profilePath.empty()) {
|
||||
profilePath = DataDirectories::profile();
|
||||
barrier::fs::path profile_path = argsBase().m_profileDirectory;
|
||||
if (profile_path.empty()) {
|
||||
profile_path = barrier::DataDirectories::profile();
|
||||
}
|
||||
|
||||
auto usr_config_path = (profile_path / barrier::fs::u8path(USR_CONFIG_NAME)).u8string();
|
||||
auto sys_config_path = (barrier::DataDirectories::systemconfig() /
|
||||
barrier::fs::u8path(SYS_CONFIG_NAME)).u8string();
|
||||
|
||||
std::ostringstream buffer;
|
||||
buffer << "Start the barrier server component.\n"
|
||||
<< "\n"
|
||||
|
@ -156,8 +159,8 @@ ServerApp::help()
|
|||
<< "\n"
|
||||
<< "If no configuration file pathname is provided then the first of the\n"
|
||||
<< "following to load successfully sets the configuration:\n"
|
||||
<< " " << PathUtilities::concat(profilePath, USR_CONFIG_NAME) << "\n"
|
||||
<< " " << PathUtilities::concat(DataDirectories::systemconfig(), SYS_CONFIG_NAME) << "\n";
|
||||
<< " " << usr_config_path << "\n"
|
||||
<< " " << sys_config_path << "\n";
|
||||
|
||||
LOG((CLOG_PRINT "%s", buffer.str().c_str()));
|
||||
}
|
||||
|
@ -194,25 +197,25 @@ ServerApp::loadConfig()
|
|||
|
||||
// load the default configuration if no explicit file given
|
||||
else {
|
||||
String path = DataDirectories::profile();
|
||||
auto path = barrier::DataDirectories::profile();
|
||||
if (!path.empty()) {
|
||||
// complete path
|
||||
path = PathUtilities::concat(path, USR_CONFIG_NAME);
|
||||
path /= barrier::fs::u8path(USR_CONFIG_NAME);
|
||||
|
||||
// now try loading the user's configuration
|
||||
if (loadConfig(path)) {
|
||||
if (loadConfig(path.u8string())) {
|
||||
loaded = true;
|
||||
args().m_configFile = path;
|
||||
args().m_configFile = path.u8string();
|
||||
}
|
||||
}
|
||||
if (!loaded) {
|
||||
// try the system-wide config file
|
||||
path = DataDirectories::systemconfig();
|
||||
path = barrier::DataDirectories::systemconfig();
|
||||
if (!path.empty()) {
|
||||
path = PathUtilities::concat(path, SYS_CONFIG_NAME);
|
||||
if (loadConfig(path)) {
|
||||
path /= barrier::fs::u8path(SYS_CONFIG_NAME);
|
||||
if (loadConfig(path.u8string())) {
|
||||
loaded = true;
|
||||
args().m_configFile = path;
|
||||
args().m_configFile = path.u8string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -832,7 +835,7 @@ ServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc
|
|||
// general initialization
|
||||
m_barrierAddress = new NetworkAddress;
|
||||
args().m_config = new Config(m_events);
|
||||
args().m_exename = PathUtilities::basename(argv[0]);
|
||||
args().m_exename = ArgParser::parse_exename(argv[0]);
|
||||
|
||||
// install caller's output filter
|
||||
if (outputter != NULL) {
|
||||
|
|
|
@ -245,7 +245,7 @@ DaemonApp::logFilename()
|
|||
{
|
||||
string logFilename = ARCH->setting("LogFilename");
|
||||
if (logFilename.empty())
|
||||
logFilename = DataDirectories::global() + "\\" + LOG_FILENAME;
|
||||
logFilename = (barrier::DataDirectories::global() / LOG_FILENAME).u8string();
|
||||
MSWindowsUtil::createDirectory(logFilename, true);
|
||||
return logFilename;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "base/TMethodJob.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "base/String.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
#include <fstream>
|
||||
|
||||
enum EFileLogOutputter {
|
||||
|
|
|
@ -15,28 +15,36 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BARRIER_LIB_COMMON_DATA_DIRECTORIES_H
|
||||
#define BARRIER_LIB_COMMON_DATA_DIRECTORIES_H
|
||||
|
||||
#include <string>
|
||||
#include "io/filesystem.h"
|
||||
|
||||
namespace barrier {
|
||||
|
||||
class DataDirectories
|
||||
{
|
||||
public:
|
||||
static const std::string& profile();
|
||||
static const std::string& profile(const std::string& path);
|
||||
static const fs::path& profile();
|
||||
static const fs::path& profile(const fs::path& path);
|
||||
|
||||
static const std::string& global();
|
||||
static const std::string& global(const std::string& path);
|
||||
static const fs::path& global();
|
||||
static const fs::path& global(const fs::path& path);
|
||||
|
||||
static const std::string& systemconfig();
|
||||
static const std::string& systemconfig(const std::string& path);
|
||||
static const fs::path& systemconfig();
|
||||
static const fs::path& systemconfig(const fs::path& path);
|
||||
|
||||
static std::string ssl_fingerprints_path();
|
||||
static std::string local_ssl_fingerprints_path();
|
||||
static std::string trusted_servers_ssl_fingerprints_path();
|
||||
static std::string trusted_clients_ssl_fingerprints_path();
|
||||
static fs::path ssl_fingerprints_path();
|
||||
static fs::path local_ssl_fingerprints_path();
|
||||
static fs::path trusted_servers_ssl_fingerprints_path();
|
||||
static fs::path trusted_clients_ssl_fingerprints_path();
|
||||
static fs::path ssl_certificate_path();
|
||||
private:
|
||||
static std::string _profile;
|
||||
static std::string _global;
|
||||
static std::string _systemconfig;
|
||||
static fs::path _profile;
|
||||
static fs::path _global;
|
||||
static fs::path _systemconfig;
|
||||
};
|
||||
|
||||
} // namespace barrier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,32 +17,40 @@
|
|||
|
||||
#include "DataDirectories.h"
|
||||
|
||||
// static member
|
||||
std::string DataDirectories::_profile;
|
||||
std::string DataDirectories::_global;
|
||||
std::string DataDirectories::_systemconfig;
|
||||
namespace barrier {
|
||||
|
||||
fs::path DataDirectories::_profile;
|
||||
fs::path DataDirectories::_global;
|
||||
fs::path DataDirectories::_systemconfig;
|
||||
|
||||
static const char kFingerprintsDirName[] = "SSL/Fingerprints";
|
||||
static const char kFingerprintsLocalFilename[] = "Local.txt";
|
||||
static const char kFingerprintsTrustedServersFilename[] = "TrustedServers.txt";
|
||||
static const char kFingerprintsTrustedClientsFilename[] = "TrustedClients.txt";
|
||||
|
||||
std::string DataDirectories::ssl_fingerprints_path()
|
||||
fs::path DataDirectories::ssl_fingerprints_path()
|
||||
{
|
||||
return profile() + "/" + kFingerprintsDirName;
|
||||
return profile() / kFingerprintsDirName;
|
||||
}
|
||||
|
||||
std::string DataDirectories::local_ssl_fingerprints_path()
|
||||
fs::path DataDirectories::local_ssl_fingerprints_path()
|
||||
{
|
||||
return ssl_fingerprints_path() + "/" + kFingerprintsLocalFilename;
|
||||
return ssl_fingerprints_path() / kFingerprintsLocalFilename;
|
||||
}
|
||||
|
||||
std::string DataDirectories::trusted_servers_ssl_fingerprints_path()
|
||||
fs::path DataDirectories::trusted_servers_ssl_fingerprints_path()
|
||||
{
|
||||
return ssl_fingerprints_path() + "/" + kFingerprintsTrustedServersFilename;
|
||||
return ssl_fingerprints_path() / kFingerprintsTrustedServersFilename;
|
||||
}
|
||||
|
||||
std::string DataDirectories::trusted_clients_ssl_fingerprints_path()
|
||||
fs::path DataDirectories::trusted_clients_ssl_fingerprints_path()
|
||||
{
|
||||
return ssl_fingerprints_path() + "/" + kFingerprintsTrustedClientsFilename;
|
||||
return ssl_fingerprints_path() / kFingerprintsTrustedClientsFilename;
|
||||
}
|
||||
|
||||
fs::path DataDirectories::ssl_certificate_path()
|
||||
{
|
||||
return profile() / "SSL" / "Barrier.pem";
|
||||
}
|
||||
|
||||
} // namespace barrier
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* barrier -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2012-2016 Symless Ltd.
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file LICENSE that should have accompanied this file.
|
||||
*
|
||||
* This package is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// Prefix header for all source files of the 'deleteme' target in the 'deleteme' project.
|
||||
//
|
||||
|
||||
#include <Carbon/Carbon.h>
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* barrier -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2018 Debauchee Open Source Group
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file LICENSE that should have accompanied this file.
|
||||
*
|
||||
* This package is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These functions cover the vast majority of cases for different paths across
|
||||
windows and unixes. They are not, however, fullproof and probably don't cover
|
||||
fringe cases very well. The library below might be used as an alternative if
|
||||
these implementations prove to be insufficient. As the library's readme states
|
||||
it is simply a temporary band-aid until std::filesystem is integrated (C++17
|
||||
has it in std::experimental) and this class should also be treated as such.
|
||||
|
||||
https://github.com/wjakob/filesystem/
|
||||
|
||||
*/
|
||||
|
||||
#include "PathUtilities.h"
|
||||
|
||||
// keep the default platform delimiter as the first in the list
|
||||
#ifdef _WIN32
|
||||
static const char *Delimiters = "\\/";
|
||||
#else
|
||||
static const char *Delimiters = "/";
|
||||
#endif
|
||||
|
||||
static const char DefaultDelimiter = Delimiters[0];
|
||||
|
||||
std::string PathUtilities::basename(const std::string& path)
|
||||
{
|
||||
return path.substr(path.find_last_of(Delimiters) + 1);
|
||||
}
|
||||
|
||||
std::string PathUtilities::concat(const std::string& left, const std::string& right)
|
||||
{
|
||||
// although npos is usually (-1) we can't count on that so handle it explicitly
|
||||
auto leftEnd = left.find_last_not_of(Delimiters);
|
||||
if (leftEnd == std::string::npos)
|
||||
leftEnd = 0;
|
||||
else
|
||||
++leftEnd;
|
||||
auto rightStart = right.find_first_not_of(Delimiters, 0);
|
||||
if (rightStart == std::string::npos) {
|
||||
// both left/right are empty
|
||||
if (left.size() == 0 && right.size() == 0)
|
||||
return "";
|
||||
// right is full of delims, left is okay
|
||||
if (leftEnd > 0)
|
||||
return left.substr(0, leftEnd);
|
||||
// both left/right useless but at least one has delims
|
||||
return std::string(1, DefaultDelimiter);
|
||||
}
|
||||
if (leftEnd == 0) {
|
||||
// right is okay and not prefixed with delims, left is empty
|
||||
if (left.size() == 0 && rightStart == 0)
|
||||
return right.substr(rightStart);
|
||||
// (right is okay and prefixed with delims) OR left is full of delims
|
||||
return DefaultDelimiter + right.substr(rightStart);
|
||||
}
|
||||
// concatenation using both left and right
|
||||
return left.substr(0, leftEnd) + DefaultDelimiter + right.substr(rightStart);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* barrier -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2018 Debauchee Open Source Group
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file LICENSE that should have accompanied this file.
|
||||
*
|
||||
* This package is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class PathUtilities
|
||||
{
|
||||
public:
|
||||
static std::string basename(const std::string& path);
|
||||
static std::string concat(const std::string& left, const std::string& right);
|
||||
};
|
|
@ -22,7 +22,7 @@
|
|||
#include <sys/types.h> // getpwuid(_r)
|
||||
#include <pwd.h> // getpwuid(_r)
|
||||
|
||||
const std::string ProfileSubdir = "/barrier";
|
||||
namespace barrier {
|
||||
|
||||
static std::string pw_dir(struct passwd* pwentp)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ static std::string pw_dir(struct passwd* pwentp)
|
|||
|
||||
#ifdef HAVE_GETPWUID_R
|
||||
|
||||
static std::string unix_home()
|
||||
static fs::path unix_home()
|
||||
{
|
||||
long size = -1;
|
||||
#if defined(_SC_GETPW_R_SIZE_MAX)
|
||||
|
@ -46,47 +46,47 @@ static std::string unix_home()
|
|||
struct passwd* pwentp;
|
||||
std::string buffer(size, 0);
|
||||
getpwuid_r(getuid(), &pwent, &buffer[0], size, &pwentp);
|
||||
return pw_dir(pwentp);
|
||||
return fs::u8path(pw_dir(pwentp));
|
||||
}
|
||||
|
||||
#else // not HAVE_GETPWUID_R
|
||||
|
||||
static std::string unix_home()
|
||||
static fs::path unix_home()
|
||||
{
|
||||
return pw_dir(getpwuid(getuid()));
|
||||
return fs::u8path(pw_dir(getpwuid(getuid())));
|
||||
}
|
||||
|
||||
#endif // HAVE_GETPWUID_R
|
||||
|
||||
static std::string profile_basedir()
|
||||
static fs::path profile_basedir()
|
||||
{
|
||||
#ifdef WINAPI_XWINDOWS
|
||||
// linux/bsd adheres to freedesktop standards
|
||||
// https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
const char* dir = std::getenv("XDG_DATA_HOME");
|
||||
if (dir != NULL)
|
||||
return dir;
|
||||
return unix_home() + "/.local/share";
|
||||
return fs::u8path(dir);
|
||||
return unix_home() / ".local/share";
|
||||
#else
|
||||
// macos has its own standards
|
||||
// https://developer.apple.com/library/content/documentation/General/Conceptual/MOSXAppProgrammingGuide/AppRuntime/AppRuntime.html
|
||||
return unix_home() + "/Library/Application Support";
|
||||
return unix_home() / "Library/Application Support";
|
||||
#endif
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::profile()
|
||||
const fs::path& DataDirectories::profile()
|
||||
{
|
||||
if (_profile.empty())
|
||||
_profile = profile_basedir() + ProfileSubdir;
|
||||
_profile = profile_basedir() / "barrier";
|
||||
return _profile;
|
||||
}
|
||||
const std::string& DataDirectories::profile(const std::string& path)
|
||||
const fs::path& DataDirectories::profile(const fs::path& path)
|
||||
{
|
||||
_profile = path;
|
||||
return _profile;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::global()
|
||||
const fs::path& DataDirectories::global()
|
||||
{
|
||||
if (_global.empty())
|
||||
// TODO: where on a unix system should public/global shared data go?
|
||||
|
@ -94,21 +94,23 @@ const std::string& DataDirectories::global()
|
|||
_global = "/tmp";
|
||||
return _global;
|
||||
}
|
||||
const std::string& DataDirectories::global(const std::string& path)
|
||||
const fs::path& DataDirectories::global(const fs::path& path)
|
||||
{
|
||||
_global = path;
|
||||
return _global;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::systemconfig()
|
||||
const fs::path& DataDirectories::systemconfig()
|
||||
{
|
||||
if (_systemconfig.empty())
|
||||
_systemconfig = "/etc";
|
||||
return _systemconfig;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::systemconfig(const std::string& path)
|
||||
const fs::path& DataDirectories::systemconfig(const fs::path& path)
|
||||
{
|
||||
_systemconfig = path;
|
||||
return _systemconfig;
|
||||
}
|
||||
|
||||
} // namespace barrier
|
||||
|
|
|
@ -20,43 +20,45 @@
|
|||
|
||||
#include <Shlobj.h>
|
||||
|
||||
std::string known_folder_path(const KNOWNFOLDERID& id)
|
||||
namespace barrier {
|
||||
|
||||
fs::path known_folder_path(const KNOWNFOLDERID& id)
|
||||
{
|
||||
std::string path;
|
||||
fs::path path;
|
||||
WCHAR* buffer;
|
||||
HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &buffer);
|
||||
if (result == S_OK) {
|
||||
path = win_wchar_to_utf8(buffer);
|
||||
path = fs::path(std::wstring(buffer));
|
||||
CoTaskMemFree(buffer);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::profile()
|
||||
const fs::path& DataDirectories::profile()
|
||||
{
|
||||
if (_profile.empty())
|
||||
_profile = known_folder_path(FOLDERID_LocalAppData) + "\\Barrier";
|
||||
_profile = known_folder_path(FOLDERID_LocalAppData) / "Barrier";
|
||||
return _profile;
|
||||
}
|
||||
const std::string& DataDirectories::profile(const std::string& path)
|
||||
const fs::path& DataDirectories::profile(const fs::path& path)
|
||||
{
|
||||
_profile = path;
|
||||
return _profile;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::global()
|
||||
const fs::path& DataDirectories::global()
|
||||
{
|
||||
if (_global.empty())
|
||||
_global = known_folder_path(FOLDERID_ProgramData) + "\\Barrier";
|
||||
_global = known_folder_path(FOLDERID_ProgramData) / "Barrier";
|
||||
return _global;
|
||||
}
|
||||
const std::string& DataDirectories::global(const std::string& path)
|
||||
const fs::path& DataDirectories::global(const fs::path& path)
|
||||
{
|
||||
_global = path;
|
||||
return _global;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::systemconfig()
|
||||
const fs::path& DataDirectories::systemconfig()
|
||||
{
|
||||
// systemconfig() is a special case in that it will track the current value
|
||||
// of global() unless and until it is explicitly set otherwise
|
||||
|
@ -66,8 +68,10 @@ const std::string& DataDirectories::systemconfig()
|
|||
return _systemconfig;
|
||||
}
|
||||
|
||||
const std::string& DataDirectories::systemconfig(const std::string& path)
|
||||
const fs::path& DataDirectories::systemconfig(const fs::path& path)
|
||||
{
|
||||
_systemconfig = path;
|
||||
return _systemconfig;
|
||||
}
|
||||
|
||||
} // namespace barrier
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "fstream.h"
|
||||
// this header must come first so that it picks up the filesystem implementation
|
||||
#include <ghc/fs_impl.hpp>
|
||||
|
||||
#include "filesystem.h"
|
||||
#if SYSAPI_WIN32
|
||||
#include "common/win32/encoding_utilities.h"
|
||||
#endif
|
||||
|
@ -26,43 +29,42 @@ namespace barrier {
|
|||
namespace {
|
||||
|
||||
template<class Stream>
|
||||
void open_utf8_path_impl(Stream& stream, const std::string& path, std::ios_base::openmode mode)
|
||||
void open_utf8_path_impl(Stream& stream, const fs::path& path, std::ios_base::openmode mode)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
// on Windows we need to use a private constructor from wchar_t* string.
|
||||
auto wchar_path = utf8_to_win_char(path);
|
||||
stream.open(wchar_path.data(), mode);
|
||||
// on Windows we need to use a non-standard constructor from wchar_t* string
|
||||
// which fs::path::native() returns
|
||||
stream.open(path.native().c_str(), mode);
|
||||
#else
|
||||
stream.open(path.c_str(), mode);
|
||||
stream.open(path.native().c_str(), mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void open_utf8_path(std::ifstream& stream, const std::string& path, std::ios_base::openmode mode)
|
||||
void open_utf8_path(std::ifstream& stream, const fs::path& path, std::ios_base::openmode mode)
|
||||
{
|
||||
open_utf8_path_impl(stream, path, mode);
|
||||
}
|
||||
|
||||
void open_utf8_path(std::ofstream& stream, const std::string& path, std::ios_base::openmode mode)
|
||||
void open_utf8_path(std::ofstream& stream, const fs::path& path, std::ios_base::openmode mode)
|
||||
{
|
||||
open_utf8_path_impl(stream, path, mode);
|
||||
}
|
||||
|
||||
void open_utf8_path(std::fstream& stream, const std::string& path, std::ios_base::openmode mode)
|
||||
void open_utf8_path(std::fstream& stream, const fs::path& path, std::ios_base::openmode mode)
|
||||
{
|
||||
open_utf8_path_impl(stream, path, mode);
|
||||
}
|
||||
|
||||
std::FILE* fopen_utf8_path(const std::string& path, const std::string& mode)
|
||||
std::FILE* fopen_utf8_path(const fs::path& path, const std::string& mode)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
auto wchar_path = utf8_to_win_char(path);
|
||||
auto wchar_mode = utf8_to_win_char(mode);
|
||||
return _wfopen(reinterpret_cast<wchar_t*>(wchar_path.data()),
|
||||
return _wfopen(path.native().c_str(),
|
||||
reinterpret_cast<wchar_t*>(wchar_mode.data()));
|
||||
#else
|
||||
return std::fopen(path.c_str(), mode.c_str());
|
||||
return std::fopen(path.native().c_str(), mode.c_str());
|
||||
#endif
|
||||
}
|
||||
|
|
@ -15,24 +15,27 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BARRIER_LIB_IO_FSTREAM_H
|
||||
#define BARRIER_LIB_IO_FSTREAM_H
|
||||
#ifndef BARRIER_LIB_IO_FILESYSTEM_H
|
||||
#define BARRIER_LIB_IO_FILESYSTEM_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <iosfwd>
|
||||
#include <ios>
|
||||
#include <ghc/fs_fwd.hpp>
|
||||
|
||||
namespace barrier {
|
||||
|
||||
void open_utf8_path(std::ifstream& stream, const std::string& path,
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
void open_utf8_path(std::ifstream& stream, const fs::path& path,
|
||||
std::ios_base::openmode mode = std::ios_base::in);
|
||||
void open_utf8_path(std::ofstream& stream, const std::string& path,
|
||||
void open_utf8_path(std::ofstream& stream, const fs::path& path,
|
||||
std::ios_base::openmode mode = std::ios_base::out);
|
||||
void open_utf8_path(std::fstream& stream, const std::string& path,
|
||||
void open_utf8_path(std::fstream& stream, const fs::path& path,
|
||||
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
|
||||
|
||||
std::FILE* fopen_utf8_path(const std::string& path, const std::string& mode);
|
||||
std::FILE* fopen_utf8_path(const fs::path& path, const std::string& mode);
|
||||
|
||||
} // namespace barrier
|
||||
|
||||
#endif
|
||||
#endif // BARRIER_LIB_IO_FILESYSTEM_H
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "base/String.h"
|
||||
#include "FingerprintDatabase.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
|
||||
#include "base/String.h"
|
||||
#include "FingerprintDatabase.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
namespace barrier {
|
||||
|
||||
void FingerprintDatabase::read(const std::string& path)
|
||||
void FingerprintDatabase::read(const fs::path& path)
|
||||
{
|
||||
std::ifstream file;
|
||||
open_utf8_path(file, path, std::ios_base::in);
|
||||
read_stream(file);
|
||||
}
|
||||
|
||||
void FingerprintDatabase::write(const std::string& path)
|
||||
void FingerprintDatabase::write(const fs::path& path)
|
||||
{
|
||||
std::ofstream file;
|
||||
open_utf8_path(file, path, std::ios_base::out);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define BARRIER_LIB_NET_FINGERPRINT_DATABASE_H
|
||||
|
||||
#include "FingerprintData.h"
|
||||
#include "io/filesystem.h"
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -27,8 +28,8 @@ namespace barrier {
|
|||
|
||||
class FingerprintDatabase {
|
||||
public:
|
||||
void read(const std::string& path);
|
||||
void write(const std::string& path);
|
||||
void read(const fs::path& path);
|
||||
void write(const fs::path& path);
|
||||
|
||||
void read_stream(std::istream& stream);
|
||||
void write_stream(std::ostream& stream);
|
||||
|
|
|
@ -25,13 +25,6 @@
|
|||
#include "common/DataDirectories.h"
|
||||
#include "base/String.h"
|
||||
|
||||
static const char s_certificateDir[] = { "SSL" };
|
||||
static const char s_certificateFilename[] = { "Barrier.pem" };
|
||||
|
||||
//
|
||||
// SecureListenSocket
|
||||
//
|
||||
|
||||
SecureListenSocket::SecureListenSocket(
|
||||
IEventQueue* events,
|
||||
SocketMultiplexer* socketMultiplexer,
|
||||
|
@ -55,12 +48,7 @@ SecureListenSocket::accept()
|
|||
setListeningJob();
|
||||
}
|
||||
|
||||
std::string certificateFilename = barrier::string::sprintf("%s/%s/%s",
|
||||
DataDirectories::profile().c_str(),
|
||||
s_certificateDir,
|
||||
s_certificateFilename);
|
||||
|
||||
bool loaded = socket->loadCertificates(certificateFilename);
|
||||
bool loaded = socket->load_certificates(barrier::DataDirectories::ssl_certificate_path());
|
||||
if (!loaded) {
|
||||
delete socket;
|
||||
return NULL;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "base/Log.h"
|
||||
#include "base/String.h"
|
||||
#include "common/DataDirectories.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
#include "net/FingerprintDatabase.h"
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
@ -327,39 +327,35 @@ SecureSocket::initSsl(bool server)
|
|||
initContext(server);
|
||||
}
|
||||
|
||||
bool SecureSocket::loadCertificates(const std::string& filename)
|
||||
bool SecureSocket::load_certificates(const barrier::fs::path& path)
|
||||
{
|
||||
if (filename.empty()) {
|
||||
if (path.empty()) {
|
||||
showError("ssl certificate is not specified");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
std::ifstream file(filename.c_str());
|
||||
bool exist = file.good();
|
||||
file.close();
|
||||
|
||||
if (!exist) {
|
||||
showError("ssl certificate doesn't exist: " + filename);
|
||||
if (!barrier::fs::is_regular_file(path)) {
|
||||
showError("ssl certificate doesn't exist: " + path.u8string());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int r = 0;
|
||||
r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename.c_str(), SSL_FILETYPE_PEM);
|
||||
r = SSL_CTX_use_certificate_file(m_ssl->m_context, path.u8string().c_str(), SSL_FILETYPE_PEM);
|
||||
if (r <= 0) {
|
||||
showError("could not use ssl certificate: " + filename);
|
||||
showError("could not use ssl certificate: " + path.u8string());
|
||||
return false;
|
||||
}
|
||||
|
||||
r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, filename.c_str(), SSL_FILETYPE_PEM);
|
||||
r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, path.u8string().c_str(), SSL_FILETYPE_PEM);
|
||||
if (r <= 0) {
|
||||
showError("could not use ssl private key: " + filename);
|
||||
showError("could not use ssl private key: " + path.u8string());
|
||||
return false;
|
||||
}
|
||||
|
||||
r = SSL_CTX_check_private_key(m_ssl->m_context);
|
||||
if (!r) {
|
||||
showError("could not verify ssl private key: " + filename);
|
||||
showError("could not verify ssl private key: " + path.u8string());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -674,20 +670,20 @@ SecureSocket::verifyCertFingerprint()
|
|||
barrier::format_ssl_fingerprint(fingerprint_sha1.data).c_str(),
|
||||
barrier::format_ssl_fingerprint(fingerprint_sha256.data).c_str()));
|
||||
|
||||
auto fingerprint_db_path = DataDirectories::trusted_servers_ssl_fingerprints_path();
|
||||
auto fingerprint_db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path();
|
||||
|
||||
// Provide debug hint as to what file is being used to verify fingerprint trust
|
||||
LOG((CLOG_NOTE "fingerprint_db_path: %s", fingerprint_db_path.c_str()));
|
||||
LOG((CLOG_NOTE "fingerprint_db_path: %s", fingerprint_db_path.u8string().c_str()));
|
||||
|
||||
barrier::FingerprintDatabase db;
|
||||
db.read(fingerprint_db_path);
|
||||
|
||||
if (!db.fingerprints().empty()) {
|
||||
LOG((CLOG_NOTE "Read %d fingerprints from: %s", db.fingerprints().size(),
|
||||
fingerprint_db_path.c_str()));
|
||||
fingerprint_db_path.u8string().c_str()));
|
||||
} else {
|
||||
LOG((CLOG_NOTE "Could not read fingerprints from: %s",
|
||||
fingerprint_db_path.c_str()));
|
||||
fingerprint_db_path.u8string().c_str()));
|
||||
}
|
||||
|
||||
if (db.is_trusted(fingerprint_sha256)) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "net/TCPSocket.h"
|
||||
#include "net/XSocket.h"
|
||||
#include "io/filesystem.h"
|
||||
|
||||
class IEventQueue;
|
||||
class SocketMultiplexer;
|
||||
|
@ -55,7 +56,7 @@ public:
|
|||
EJobResult doRead() override;
|
||||
EJobResult doWrite() override;
|
||||
void initSsl(bool server);
|
||||
bool loadCertificates(const std::string& filename);
|
||||
bool load_certificates(const barrier::fs::path& path);
|
||||
|
||||
private:
|
||||
// SSL
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "SecureUtils.h"
|
||||
#include "base/String.h"
|
||||
#include "base/finally.h"
|
||||
#include "io/fstream.h"
|
||||
#include "io/filesystem.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
|
|
@ -574,7 +574,7 @@ MSWindowsHook::install()
|
|||
g_fakeServerInput = false;
|
||||
|
||||
// setup immune keys
|
||||
g_immuneKeysPath = DataDirectories::profile() + "\\ImmuneKeys.txt";
|
||||
g_immuneKeysPath = (barrier::DataDirectories::profile() / "ImmuneKeys.txt").u8string();
|
||||
g_immuneKeys = immune_keys_list();
|
||||
LOG((CLOG_DEBUG "Found %u immune keys in %s", g_immuneKeys.size(), g_immuneKeysPath.c_str()));
|
||||
|
||||
|
|
Loading…
Reference in New Issue