2020-10-09 19:13:42 +01:00
|
|
|
#include "frontends/common2/configuration.h"
|
2020-10-11 09:49:50 +01:00
|
|
|
#include <frontends/common2/programoptions.h>
|
2017-06-08 21:58:26 +01:00
|
|
|
|
|
|
|
#include "Log.h"
|
2020-07-05 13:20:03 +01:00
|
|
|
#include "linux/windows/files.h"
|
2020-10-11 09:49:50 +01:00
|
|
|
#include "frontends/qapple/applicationname.h"
|
2017-06-08 21:58:26 +01:00
|
|
|
|
|
|
|
#include <boost/property_tree/ini_parser.hpp>
|
2020-10-11 09:49:50 +01:00
|
|
|
#include <boost/algorithm/string/replace.hpp>
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-12-03 15:57:12 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
namespace
|
2017-06-08 21:58:26 +01:00
|
|
|
{
|
2020-10-11 09:49:50 +01:00
|
|
|
|
2020-12-04 19:58:49 +00:00
|
|
|
void parseOption(const std::string & s, std::string & path, std::string & value)
|
|
|
|
{
|
|
|
|
const size_t pos = s.find('=');
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Invalid option format: " + s + ", expected: section.key=value");
|
|
|
|
}
|
|
|
|
path = s.substr(0, pos);
|
|
|
|
std::replace(path.begin(), path.end(), '_', ' ');
|
|
|
|
value = s.substr(pos + 1);
|
|
|
|
std::replace(value.begin(), value.end(), '_', ' ');
|
|
|
|
}
|
|
|
|
|
2020-10-11 09:49:50 +01:00
|
|
|
struct KeyEncodedLess
|
|
|
|
{
|
|
|
|
static std::string decodeKey(const std::string & key)
|
|
|
|
{
|
|
|
|
std::string result = key;
|
|
|
|
// quick implementation, just to make it work.
|
|
|
|
// is there a library function available somewhere?
|
|
|
|
boost::algorithm::replace_all(result, "%20", " ");
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()( const std::string & lhs, const std::string & rhs ) const
|
|
|
|
{
|
|
|
|
const std::string key1 = decodeKey(lhs);
|
|
|
|
const std::string key2 = decodeKey(rhs);
|
|
|
|
return key1 < key2;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
class Configuration
|
|
|
|
{
|
|
|
|
public:
|
2020-10-11 09:49:50 +01:00
|
|
|
typedef boost::property_tree::basic_ptree<std::string, std::string, KeyEncodedLess> ini_t;
|
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
Configuration(const std::string & filename, const bool saveOnExit);
|
|
|
|
~Configuration();
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
static std::shared_ptr<Configuration> instance;
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
template<typename T>
|
|
|
|
T getValue(const std::string & section, const std::string & key) const;
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
template<typename T>
|
|
|
|
void putValue(const std::string & section, const std::string & key, const T & value);
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 09:49:50 +01:00
|
|
|
const ini_t & getProperties() const;
|
2017-09-29 21:39:55 +01:00
|
|
|
|
2020-12-04 19:58:49 +00:00
|
|
|
void addExtraOptions(const std::vector<std::string> & options);
|
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
private:
|
|
|
|
const std::string myFilename;
|
2020-10-11 09:49:50 +01:00
|
|
|
const bool mySaveOnExit;
|
|
|
|
|
|
|
|
static std::string decodeKey(const std::string & key);
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 09:49:50 +01:00
|
|
|
ini_t myINI;
|
2020-10-11 08:26:42 +01:00
|
|
|
};
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
std::shared_ptr<Configuration> Configuration::instance;
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
Configuration::Configuration(const std::string & filename, const bool saveOnExit) : myFilename(filename), mySaveOnExit(saveOnExit)
|
2019-11-03 10:21:02 +00:00
|
|
|
{
|
2020-10-11 08:26:42 +01:00
|
|
|
if (GetFileAttributes(myFilename.c_str()) != INVALID_FILE_ATTRIBUTES)
|
|
|
|
{
|
|
|
|
boost::property_tree::ini_parser::read_ini(myFilename, myINI);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LogFileOutput("Registry: configuration file '%s' not found\n", filename.c_str());
|
|
|
|
}
|
2019-11-03 10:21:02 +00:00
|
|
|
}
|
2020-10-11 08:26:42 +01:00
|
|
|
|
|
|
|
Configuration::~Configuration()
|
2019-11-03 10:21:02 +00:00
|
|
|
{
|
2020-10-11 08:26:42 +01:00
|
|
|
if (mySaveOnExit)
|
|
|
|
{
|
|
|
|
boost::property_tree::ini_parser::write_ini(myFilename, myINI);
|
|
|
|
}
|
2019-11-03 10:21:02 +00:00
|
|
|
}
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 09:49:50 +01:00
|
|
|
const Configuration::ini_t & Configuration::getProperties() const
|
2020-10-11 08:26:42 +01:00
|
|
|
{
|
|
|
|
return myINI;
|
|
|
|
}
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
template <typename T>
|
|
|
|
T Configuration::getValue(const std::string & section, const std::string & key) const
|
|
|
|
{
|
|
|
|
const std::string path = section + "." + key;
|
|
|
|
const T value = myINI.get<T>(path);
|
|
|
|
return value;
|
|
|
|
}
|
2017-09-29 21:39:55 +01:00
|
|
|
|
2020-10-11 08:26:42 +01:00
|
|
|
template <typename T>
|
|
|
|
void Configuration::putValue(const std::string & section, const std::string & key, const T & value)
|
|
|
|
{
|
|
|
|
const std::string path = section + "." + key;
|
|
|
|
myINI.put(path, value);
|
|
|
|
}
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2020-12-04 19:58:49 +00:00
|
|
|
void Configuration::addExtraOptions(const std::vector<std::string> & options)
|
|
|
|
{
|
|
|
|
for (const std::string & option : options)
|
|
|
|
{
|
|
|
|
std::string path, value;
|
|
|
|
parseOption(option, path, value);
|
|
|
|
myINI.put(path, value);
|
|
|
|
}
|
|
|
|
}
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
|
|
|
|
2020-10-11 09:49:50 +01:00
|
|
|
void InitializeRegistry(const EmulatorOptions & options)
|
2017-06-08 21:58:26 +01:00
|
|
|
{
|
2020-10-11 09:49:50 +01:00
|
|
|
std::string filename;
|
|
|
|
bool saveOnExit;
|
|
|
|
|
2020-12-03 15:57:12 +00:00
|
|
|
const char* homeDir = getenv("HOME");
|
|
|
|
if (!homeDir)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("${HOME} not set, cannot locate configuration file");
|
|
|
|
}
|
|
|
|
|
2020-10-11 09:49:50 +01:00
|
|
|
if (options.useQtIni)
|
|
|
|
{
|
|
|
|
filename = std::string(homeDir) + "/.config/" + ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf";
|
|
|
|
saveOnExit = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-12-03 15:57:12 +00:00
|
|
|
const std::string dir = std::string(homeDir) + "/.applewin";
|
|
|
|
const int status = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
|
|
|
filename = dir + "/applewin.conf";
|
|
|
|
if (!status || (status == EEXIST))
|
|
|
|
{
|
|
|
|
saveOnExit = options.saveConfigurationOnExit;
|
|
|
|
}
|
2020-12-05 20:34:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
saveOnExit = false;
|
|
|
|
}
|
2020-10-11 09:49:50 +01:00
|
|
|
}
|
|
|
|
|
2020-12-04 19:58:49 +00:00
|
|
|
std::shared_ptr<Configuration> config(new Configuration(filename, saveOnExit));
|
|
|
|
config->addExtraOptions(options.registryOptions);
|
|
|
|
std::swap(Configuration::instance, config);
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL RegLoadString (LPCTSTR section, LPCTSTR key, BOOL peruser,
|
|
|
|
LPTSTR buffer, DWORD chars)
|
|
|
|
{
|
|
|
|
BOOL result;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
const std::string s = Configuration::instance->getValue<std::string>(section, key);
|
|
|
|
strncpy(buffer, s.c_str(), chars);
|
|
|
|
buffer[chars - 1] = 0;
|
|
|
|
result = TRUE;
|
2017-06-11 10:21:28 +01:00
|
|
|
LogFileOutput("RegLoadString: %s - %s = %s\n", section, key, buffer);
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
result = FALSE;
|
2017-06-11 10:21:28 +01:00
|
|
|
LogFileOutput("RegLoadString: %s - %s = ??\n", section, key);
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL RegLoadValue (LPCTSTR section, LPCTSTR key, BOOL peruser, DWORD *value)
|
|
|
|
{
|
|
|
|
BOOL result;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
*value = Configuration::instance->getValue<DWORD>(section, key);
|
|
|
|
result = TRUE;
|
2017-06-11 10:21:28 +01:00
|
|
|
LogFileOutput("RegLoadValue: %s - %s = %d\n", section, key, *value);
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
result = FALSE;
|
2017-06-11 10:21:28 +01:00
|
|
|
LogFileOutput("RegLoadValue: %s - %s = ??\n", section, key);
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
2017-06-11 10:21:28 +01:00
|
|
|
return result;
|
|
|
|
}
|
2017-06-08 21:58:26 +01:00
|
|
|
|
2017-06-11 10:21:28 +01:00
|
|
|
BOOL RegLoadValue (LPCTSTR section, LPCTSTR key, BOOL peruser, BOOL *value)
|
|
|
|
{
|
|
|
|
BOOL result;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
*value = Configuration::instance->getValue<BOOL>(section, key);
|
|
|
|
result = TRUE;
|
|
|
|
LogFileOutput("RegLoadValue: %s - %s = %d\n", section, key, *value);
|
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
result = FALSE;
|
|
|
|
LogFileOutput("RegLoadValue: %s - %s = ??\n", section, key);
|
|
|
|
}
|
2017-06-08 21:58:26 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-09-21 09:58:29 +01:00
|
|
|
void RegSaveString (LPCTSTR section, LPCTSTR key, BOOL peruser, const std::string & buffer)
|
2017-06-08 21:58:26 +01:00
|
|
|
{
|
|
|
|
Configuration::instance->putValue(section, key, buffer);
|
2019-09-21 09:58:29 +01:00
|
|
|
LogFileOutput("RegSaveString: %s - %s = %s\n", section, key, buffer.c_str());
|
2017-06-08 21:58:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RegSaveValue (LPCTSTR section, LPCTSTR key, BOOL peruser, DWORD value)
|
|
|
|
{
|
|
|
|
Configuration::instance->putValue(section, key, value);
|
|
|
|
LogFileOutput("RegSaveValue: %s - %s = %d\n", section, key, value);
|
|
|
|
}
|