8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 21:23:04 +01:00

Post-fixes by Andrey Kravchenko: Move ENV/FILE parsing into a separate routine. Validate configuration key before value. Ensure the username/password is not specified multiple times.

This commit is contained in:
Dmitry Yemanov 2024-12-11 15:39:30 +03:00
parent b37ac359f3
commit ebfc854059

View File

@ -52,8 +52,8 @@ using namespace Replication;
namespace namespace
{ {
const char* REPLICATION_CFGFILE = "replication.conf"; const char* REPLICATION_CFGFILE = "replication.conf";
constexpr const char* KEY_ENV = "env"; constexpr const char* KEY_SUFFIX_ENV = "env";
constexpr const char* KEY_FILE = "file"; constexpr const char* KEY_SUFFIX_FILE = "file";
const ULONG DEFAULT_BUFFER_SIZE = 1024 * 1024; // 1 MB const ULONG DEFAULT_BUFFER_SIZE = 1024 * 1024; // 1 MB
const ULONG DEFAULT_SEGMENT_SIZE = 16 * 1024 * 1024; // 16 MB const ULONG DEFAULT_SEGMENT_SIZE = 16 * 1024 * 1024; // 16 MB
@ -104,30 +104,25 @@ namespace
status->setErrors(sv.value()); status->setErrors(sv.value());
} }
void parseSyncReplica(const ConfigFile::Parameters& params, SyncReplica& output) void parseExternalValue(const string& key, const string& value, string& output)
{ {
for (const auto& el : params) const auto pos = key.rfind('_');
if (pos == string::npos)
{ {
string key(el.name.c_str()); output = value.c_str();
string value(el.value); return;
}
if (value.isEmpty()) string temp;
continue;
auto pos = key.rfind('_');
if (pos != string::npos)
{
const string key_source = key.substr(pos + 1); const string key_source = key.substr(pos + 1);
if (key_source.equals(KEY_ENV)) if (key_source.equals(KEY_SUFFIX_ENV))
{ {
fb_utils::readenv(value.c_str(), value); fb_utils::readenv(value.c_str(), temp);
if (value.isEmpty()) if (temp.isEmpty())
configError("missing environment variable", output.database, value); configError("missing environment variable", key, value);
key = key.substr(0, pos);
} }
else if (key_source.equals(KEY_FILE)) else if (key_source.equals(KEY_SUFFIX_FILE))
{ {
PathName filename = value.c_str(); PathName filename = value.c_str();
PathUtils::fixupSeparators(filename); PathUtils::fixupSeparators(filename);
@ -136,32 +131,49 @@ namespace
AutoPtr<FILE> file(os_utils::fopen(filename.c_str(), "rt")); AutoPtr<FILE> file(os_utils::fopen(filename.c_str(), "rt"));
if (!file) if (!file)
configError("missing or inaccessible file", output.database, filename.c_str()); configError("missing or inaccessible file", key, filename.c_str());
// skip first empty lines // skip first empty lines
value = "";
do do
{ {
if (feof(file)) if (feof(file))
break; break;
if (!value.LoadFromFile(file)) if (!temp.LoadFromFile(file))
break; break;
value.alltrim(" \t\r"); temp.alltrim(" \t\r");
} while (value.isEmpty()); } while (temp.isEmpty());
if (temp.isEmpty())
configError("empty file", key, filename.c_str());
}
output = temp.c_str();
}
void parseSyncReplica(const ConfigFile::Parameters& params, SyncReplica& output)
{
for (const auto& el : params)
{
const string key(el.name.c_str());
const string value(el.value);
if (value.isEmpty()) if (value.isEmpty())
configError("empty file", output.database, filename.c_str()); continue;
key = key.substr(0, pos); if (key.find("username") == 0)
{
if (output.username.hasData())
configError("multiple values", output.database, "username");
parseExternalValue(key, value, output.username);
} }
else if (key.find("password") == 0)
{
if (output.password.hasData())
configError("multiple values", output.database, "password");
parseExternalValue(key, value, output.password);
} }
if (key == "username")
output.username = value.c_str();
else if (key == "password")
output.password = value.c_str();
else else
configError("unknown parameter", output.database, key); configError("unknown parameter", output.database, key);
} }