304 lines
7.1 KiB
C++
304 lines
7.1 KiB
C++
#include "objects.h"
|
|
#include "inifile.h"
|
|
#include "osutils.h"
|
|
#include "lang.h"
|
|
|
|
SettingsFile &settings_file()
|
|
{
|
|
static SettingsFile file_;
|
|
return file_;
|
|
}
|
|
|
|
long StrToIntDef(const char *str, long default_value)
|
|
{
|
|
size_t len = strlen(str);
|
|
if (len == 0)
|
|
return default_value;
|
|
|
|
char *end;
|
|
long res = strtol(str, &end, 0);
|
|
if (end != str + len)
|
|
return default_value;
|
|
|
|
return res;
|
|
}
|
|
|
|
uint64_t StrToInt64Def(const char *str, uint64_t default_value)
|
|
{
|
|
size_t len = strlen(str);
|
|
if (len == 0)
|
|
return default_value;
|
|
|
|
char *end;
|
|
uint64_t res = _strtoi64(str, &end, 0);
|
|
if (end != str + len)
|
|
return default_value;
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* BaseIniFile
|
|
*/
|
|
|
|
int BaseIniFile::ReadInt(const char *section, const char *name, int default_value) const
|
|
{
|
|
std::string str = ReadString(section, name);
|
|
return StrToIntDef(str.c_str(), default_value);
|
|
}
|
|
|
|
uint64_t BaseIniFile::ReadInt64(const char *section, const char *name, uint64_t default_value) const
|
|
{
|
|
std::string str = ReadString(section, name);
|
|
return StrToInt64Def(str.c_str(), default_value);
|
|
}
|
|
|
|
void BaseIniFile::WriteInt(const char *section, const char *name, int value)
|
|
{
|
|
WriteString(section, name, string_format("%d", value).c_str());
|
|
}
|
|
|
|
bool BaseIniFile::ReadBool(const char *section, const char *name, bool default_value) const
|
|
{
|
|
return ReadInt(section, name, default_value ? 1 : 0) != 0;
|
|
}
|
|
|
|
void BaseIniFile::WriteBool(const char *section, const char *name, bool value)
|
|
{
|
|
WriteString(section, name, value ? "1" : "0");
|
|
}
|
|
|
|
/**
|
|
* IniFile
|
|
*/
|
|
|
|
IniFile::IniFile(const char *file_name)
|
|
: BaseIniFile(), file_name_(file_name)
|
|
{
|
|
|
|
}
|
|
|
|
std::string IniFile::ReadString(const char *section, const char *name, const char *default_value) const
|
|
{
|
|
return os::ReadIniString(section, name, default_value, file_name_.c_str());
|
|
}
|
|
|
|
void IniFile::WriteString(const char *section, const char *name, const char *value)
|
|
{
|
|
if (!os::WriteIniString(section, name, value, file_name_.c_str()))
|
|
throw std::runtime_error(string_format("Unable to write to %s", file_name_.c_str()));
|
|
}
|
|
|
|
bool IniFile::DeleteKey(const char *section, const char *name)
|
|
{
|
|
return os::WriteIniString(section, name, NULL, file_name_.c_str());
|
|
}
|
|
|
|
std::vector<std::string> IniFile::ReadSection(const char *section, const char *name_mask) const
|
|
{
|
|
std::vector<std::string> res;
|
|
std::string buffer = os::ReadIniString(section, NULL, NULL, file_name_.c_str());
|
|
const char *p = buffer.c_str();
|
|
while (*p) {
|
|
std::string str = p;
|
|
if (!name_mask || str.find(name_mask) == 0)
|
|
res.push_back(str);
|
|
p += str.size() + 1;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void IniFile::EraseSection(const char *section)
|
|
{
|
|
os::WriteIniString(section, NULL, NULL, file_name_.c_str());
|
|
}
|
|
|
|
/**
|
|
* SettingsFile
|
|
*/
|
|
|
|
#ifdef VMP_GNU
|
|
int GlobalLocker::depth;
|
|
#endif
|
|
|
|
SettingsFile::SettingsFile()
|
|
: IObject(), document_(NULL), last_write_time_(0), watermarks_node_created_(false), auto_save_project_(false)
|
|
{
|
|
file_name_ = os::CombineThisAppDataDirectory("VMProtect.dat");
|
|
if (!os::FileExists(file_name_.c_str()))
|
|
os::PathCreate(os::ExtractFilePath(file_name_.c_str()).c_str());
|
|
|
|
language_manager_ = new LanguageManager();
|
|
language_ = os::GetCurrentLocale();
|
|
if (!language_manager_->GetLanguageById(language_)) {
|
|
// remove country code
|
|
size_t i = language_.find('_');
|
|
if (i != std::string::npos)
|
|
language_ = language_.substr(0, i);
|
|
}
|
|
|
|
document_ = new TiXmlDocument();
|
|
Open();
|
|
|
|
if (settings_node_) {
|
|
settings_node_->QueryStringAttribute("Language", &language_);
|
|
settings_node_->QueryBoolAttribute("AutoSaveProject", &auto_save_project_);
|
|
}
|
|
|
|
if (!language_manager_->GetLanguageById(language_))
|
|
language_ = language_manager_->default_language();
|
|
language_manager_->set_language(language_);
|
|
}
|
|
|
|
SettingsFile::~SettingsFile()
|
|
{
|
|
delete document_;
|
|
delete language_manager_;
|
|
}
|
|
|
|
std::vector<std::string> SettingsFile::project_list() const
|
|
{
|
|
std::vector<std::string> res;
|
|
if (settings_node_) {
|
|
TiXmlElement *node = settings_node_->FirstChildElement("Projects");
|
|
if (node) {
|
|
node = node->FirstChildElement("Project");
|
|
while (node) {
|
|
const char *prj = node->GetText();
|
|
if (prj) res.push_back(prj);
|
|
node = node->NextSiblingElement(node->Value());
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void SettingsFile::set_project_list(const std::vector<std::string> &project_list)
|
|
{
|
|
GlobalLocker locker;
|
|
Open();
|
|
if (!settings_node_)
|
|
return;
|
|
|
|
TiXmlElement *projects_node = settings_node_->FirstChildElement("Projects");
|
|
if (!projects_node) {
|
|
projects_node = new TiXmlElement("Projects");
|
|
settings_node_->LinkEndChild(projects_node);
|
|
} else {
|
|
projects_node->Clear();
|
|
}
|
|
for (size_t i = 0; i < project_list.size(); i++) {
|
|
TiXmlElement *node = new TiXmlElement("Project");
|
|
projects_node->LinkEndChild(node);
|
|
node->LinkEndChild(new TiXmlText(project_list[i]));
|
|
}
|
|
Save();
|
|
}
|
|
|
|
void SettingsFile::set_language(const std::string &language)
|
|
{
|
|
language_ = language;
|
|
language_manager_->set_language(language_);
|
|
|
|
GlobalLocker locker;
|
|
Open();
|
|
if (!settings_node_)
|
|
return;
|
|
|
|
settings_node_->SetAttribute("Language", language_);
|
|
Save();
|
|
}
|
|
|
|
void SettingsFile::set_auto_save_project(bool auto_save_project)
|
|
{
|
|
auto_save_project_ = auto_save_project;
|
|
|
|
GlobalLocker locker;
|
|
Open();
|
|
if (!settings_node_)
|
|
return;
|
|
|
|
settings_node_->SetAttribute("AutoSaveProject", auto_save_project_);
|
|
Save();
|
|
}
|
|
|
|
size_t SettingsFile::inc_watermark_id()
|
|
{
|
|
GlobalLocker locker;
|
|
Open();
|
|
if (!watermarks_node_)
|
|
return -1;
|
|
|
|
unsigned int u;
|
|
u = 0;
|
|
watermarks_node_->QueryUnsignedAttribute("Id", &u);
|
|
watermarks_node_->SetAttribute("Id", u + 1);
|
|
Save();
|
|
return u;
|
|
}
|
|
|
|
TiXmlElement *SettingsFile::watermark_node(size_t id, bool can_create)
|
|
{
|
|
Open();
|
|
if (!watermarks_node_)
|
|
return NULL;
|
|
|
|
TiXmlElement *node = watermarks_node_->FirstChildElement("Watermark");
|
|
while (node) {
|
|
unsigned int u;
|
|
u = 0;
|
|
node->QueryUnsignedAttribute("Id", &u);
|
|
if (id == u)
|
|
return node;
|
|
node = node->NextSiblingElement(node->Value());
|
|
}
|
|
if (can_create) {
|
|
node = new TiXmlElement("Watermark");
|
|
watermarks_node_->LinkEndChild(node);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
void SettingsFile::Open()
|
|
{
|
|
GlobalLocker locker;
|
|
uint64_t cur_write_time = os::GetLastWriteTime(file_name_.c_str());
|
|
if (cur_write_time && last_write_time_ == cur_write_time)
|
|
return;
|
|
|
|
if (!document_->LoadFile(file_name_.c_str())) {
|
|
document_->Clear();
|
|
document_->LinkEndChild(new TiXmlDeclaration("1.0", "UTF-8", ""));
|
|
}
|
|
|
|
root_node_ = document_->FirstChildElement("Document");
|
|
if (!root_node_) {
|
|
root_node_ = new TiXmlElement("Document");
|
|
document_->LinkEndChild(root_node_);
|
|
}
|
|
|
|
settings_node_ = root_node_->FirstChildElement("Settings");
|
|
if (!settings_node_) {
|
|
settings_node_ = new TiXmlElement("Settings");
|
|
root_node_->LinkEndChild(settings_node_);
|
|
}
|
|
|
|
watermarks_node_ = root_node_->FirstChildElement("Watermarks");
|
|
if (!watermarks_node_) {
|
|
watermarks_node_ = new TiXmlElement("Watermarks");
|
|
root_node_->LinkEndChild(watermarks_node_);
|
|
watermarks_node_created_ = true;
|
|
} else {
|
|
watermarks_node_created_ = false;
|
|
}
|
|
|
|
last_write_time_ = os::GetLastWriteTime(file_name_.c_str());
|
|
}
|
|
|
|
void SettingsFile::Save()
|
|
{
|
|
GlobalLocker locker;
|
|
document_->SaveFile(file_name_.c_str());
|
|
|
|
last_write_time_ = os::GetLastWriteTime(file_name_.c_str());
|
|
} |