pgLab/pglab/ConnectionConfig.cpp
Eelke Klein 04723a289b Switching to linux for development of pglab.
Switched from qmake to cmake. Code changes to make it compile.
2017-08-23 08:10:01 +02:00

320 lines
7.8 KiB
C++

#include "connectionconfig.h"
#include "util.h"
#include <QCoreApplication>
#include <QProcessEnvironment>
namespace {
struct {
SslMode mode;
const char* string;
} SslModeStringTable[] = {
{ SslMode::disable, "disable" },
{ SslMode::allow, "allow" },
{ SslMode::prefer, "prefer" },
{ SslMode::require, "require" },
{ SslMode::verify_ca, "verify-ca" },
{ SslMode::verify_full, "verify-full" }
};
inline const char *valuePtr(const std::string &v)
{
return v.empty() ? nullptr : v.c_str();
}
} // end unnamed namespace
std::string SslModeToString(SslMode sm)
{
std::string result;
for (auto e : SslModeStringTable) {
if (e.mode == sm) {
result = e.string;
}
}
return result;
}
SslMode StringToSslMode(std::string s)
{
SslMode result = SslMode::allow;
for (auto e : SslModeStringTable) {
if (e.string == s) {
result = e.mode;
}
}
return result;
}
std::vector<const char*> ConnectionConfig::s_keywords = {
"host", "hostaddr", "port", "user", "password", "dbname",
"sslmode", "sslcert", "sslkey", "sslrootcrt", "sslcrl",
"client_encoding", "application_name", nullptr };
ConnectionConfig::ConnectionConfig()
: m_applicationName(QCoreApplication::applicationName().toUtf8().data())
{}
void ConnectionConfig::setName(std::string desc)
{
if (m_name != desc) {
m_dirty = true;
m_name = std::move(desc);
}
}
const std::string& ConnectionConfig::name() const
{
return m_name;
}
void ConnectionConfig::setHost(std::string host)
{
if (m_host != host) {
m_dirty = true;
m_host = std::move(host);
}
}
const std::string& ConnectionConfig::host() const
{
return m_host;
}
void ConnectionConfig::setHostAddr(std::string v)
{
if (m_hostaddr != v) {
m_dirty = true;
m_hostaddr = std::move(v);
}
}
const std::string& ConnectionConfig::hostAddr() const
{
return m_hostaddr;
}
void ConnectionConfig::setPort(unsigned short port)
{
auto p = std::to_string(port);
if (m_port != p) {
m_dirty = true;
m_port = p;
}
}
unsigned short ConnectionConfig::port() const
{
return static_cast<unsigned short>(std::stoi(m_port));
}
void ConnectionConfig::setUser(std::string v)
{
if (m_user != v) {
m_dirty = true;
m_user = std::move(v);
}
}
const std::string& ConnectionConfig::user() const
{
return m_user;
}
void ConnectionConfig::setPassword(std::string v)
{
if (m_password != v) {
m_dirty = true;
m_password = std::move(v);
}
}
const std::string& ConnectionConfig::password() const
{
return m_password;
}
void ConnectionConfig::setDbname(std::string v)
{
if (m_dbname != v) {
m_dirty = true;
m_dbname = std::move(v);
}
}
const std::string& ConnectionConfig::dbname() const
{
return m_dbname;
}
void ConnectionConfig::setSslMode(SslMode m)
{
auto v = SslModeToString(m);
if (m_sslMode != v) {
m_dirty = true;
m_sslMode = v;
}
}
SslMode ConnectionConfig::sslMode() const
{
return StringToSslMode(m_sslMode);
}
void ConnectionConfig::setSslCert(std::string v)
{
if (m_sslCert != v) {
m_dirty = true;
m_sslCert = std::move(v);
}
}
const std::string& ConnectionConfig::sslCert() const
{
return m_sslCert;
}
void ConnectionConfig::setSslKey(std::string v)
{
if (m_sslKey != v) {
m_dirty = true;
m_sslKey = std::move(v);
}
}
const std::string& ConnectionConfig::sslKey() const
{
return m_sslKey;
}
void ConnectionConfig::setSslRootCert(std::string v)
{
if (m_sslRootCert != v) {
m_dirty = true;
m_sslRootCert = std::move(v);
}
}
const std::string& ConnectionConfig::sslRootCert() const
{
return m_sslRootCert;
}
void ConnectionConfig::setSslCrl(std::string v)
{
if (m_sslCrl != v) {
m_dirty = true;
m_sslCrl = std::move(v);
}
}
const std::string& ConnectionConfig::sslCrl() const
{
return m_sslCrl;
}
const char * const * ConnectionConfig::getKeywords() const
{
return s_keywords.data();
}
const char * const * ConnectionConfig::getValues() const
{
m_values.resize(s_keywords.size(), nullptr);
m_values[0] = valuePtr(m_host);
m_values[1] = valuePtr(m_hostaddr);
m_values[2] = valuePtr(m_port);
m_values[3] = valuePtr(m_user);
m_values[4] = valuePtr(m_password);
m_values[5] = valuePtr(m_dbname);
m_values[6] = valuePtr(m_sslMode);
m_values[7] = valuePtr(m_sslCert);
m_values[8] = valuePtr(m_sslKey);
m_values[9] = valuePtr(m_sslRootCert);
m_values[10] = valuePtr(m_sslCrl);
m_values[11] = "utf8";
m_values[12] = valuePtr(m_applicationName);
return m_values.data();
}
bool ConnectionConfig::isSameDatabase(const ConnectionConfig &rhs) const
{
return m_host == rhs.m_host
&& m_hostaddr == rhs.m_hostaddr
&& m_port == rhs.m_port
&& m_user == rhs.m_user
&& m_password == rhs.m_password
&& m_dbname == rhs.m_dbname;
}
bool ConnectionConfig::dirty() const
{
return m_dirty;
}
void ConnectionConfig::clean()
{
m_dirty = false;
}
/*
PGHOST behaves the same as the host connection parameter.
PGHOSTADDR behaves the same as the hostaddr connection parameter. This can be set instead of or in addition to PGHOST to avoid DNS lookup overhead.
PGPORT behaves the same as the port connection parameter.
PGDATABASE behaves the same as the dbname connection parameter.
PGUSER behaves the same as the user connection parameter.
PGPASSWORD behaves the same as the password connection parameter. Use of this environment variable is not recommended for security reasons, as some operating systems allow non-root users to see process environment variables via ps; instead consider using the ~/.pgpass file (see Section 31.15).
PGPASSFILE specifies the name of the password file to use for lookups. If not set, it defaults to ~/.pgpass (see Section 31.15).
PGSERVICE behaves the same as the service connection parameter.
PGSERVICEFILE specifies the name of the per-user connection service file. If not set, it defaults to ~/.pg_service.conf (see Section 31.16).
PGREALM sets the Kerberos realm to use with PostgreSQL, if it is different from the local realm. If PGREALM is set, libpq applications will attempt authentication with servers for this realm and use separate ticket files to avoid conflicts with local ticket files. This environment variable is only used if GSSAPI authentication is selected by the server.
PGOPTIONS behaves the same as the options connection parameter.
PGAPPNAME behaves the same as the application_name connection parameter.
PGSSLMODE behaves the same as the sslmode connection parameter.
PGREQUIRESSL behaves the same as the requiressl connection parameter.
PGSSLCOMPRESSION behaves the same as the sslcompression connection parameter.
PGSSLCERT behaves the same as the sslcert connection parameter.
PGSSLKEY behaves the same as the sslkey connection parameter.
PGSSLROOTCERT behaves the same as the sslrootcert connection parameter.
PGSSLCRL behaves the same as the sslcrl connection parameter.
PGREQUIREPEER behaves the same as the requirepeer connection parameter.
PGKRBSRVNAME behaves the same as the krbsrvname connection parameter.
PGGSSLIB behaves the same as the gsslib connection parameter.
PGCONNECT_TIMEOUT behaves the same as the connect_timeout connection parameter.
PGCLIENTENCODING behaves the same as the client_encoding connection parameter.
*/
void ConnectionConfig::writeToEnvironment(QProcessEnvironment &env) const
{
strToEnv(env, "PGHOST", m_host);
strToEnv(env, "PGHOSTADDR", m_hostaddr);
strToEnv(env, "PGPORT", m_port);
strToEnv(env, "PGDATABASE", m_dbname);
strToEnv(env, "PGUSER", m_user);
strToEnv(env, "PGPASSWORD", m_password);
strToEnv(env, "PGSSLMODE", m_sslMode);
strToEnv(env, "PGSSLCERT", m_sslCert);
strToEnv(env, "PGSSLKEY", m_sslKey);
strToEnv(env, "PGSSLROOTCERT", m_sslRootCert);
strToEnv(env, "PGSSLCRL", m_sslCrl);
strToEnv(env, "PGSSLCOMPRESSION", "0");
strToEnv(env, "PGCONNECT_TIMEOUT", "10");
env.insert("PGCLIENTENCODING", "utf8");
env.remove("PGREQUIRESSL");
}
void ConnectionConfig::strToEnv(QProcessEnvironment &env, const QString &var, const std::string &val)
{
if (val.empty())
env.remove(var);
else
env.insert(var, stdStrToQ(val));
}