pgLab/pglablib/ConnectionConfig.cpp

402 lines
7.3 KiB
C++
Raw Normal View History

#include "ConnectionConfig.h"
#include "util.h"
#include <QCoreApplication>
#include <QProcessEnvironment>
#include <QStringBuilder>
#include <QUrl>
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
QString SslModeToString(SslMode sm)
{
2022-05-26 08:25:31 +02:00
for (auto e : SslModeStringTable)
if (e.mode == sm)
return QString::fromUtf8(e.string);
2022-05-26 08:25:31 +02:00
return {};
}
SslMode StringToSslMode(QString s)
{
SslMode result = SslMode::allow;
2022-05-26 08:25:31 +02:00
for (auto e : SslModeStringTable)
if (e.string == s)
result = e.mode;
2022-05-26 08:25:31 +02:00
return {};
}
ConnectionConfig::ConnectionConfig()
: m_applicationName(QCoreApplication::applicationName().toUtf8().data())
{}
const ConnectionGroup *ConnectionConfig::parent() const
{
return m_group;
}
void ConnectionConfig::setParent(ConnectionGroup *grp)
{
m_group = grp;
}
void ConnectionConfig::setUuid(const QUuid &uuid)
{
2022-05-26 08:25:31 +02:00
if (uuid != m_uuid)
{
m_dirty = true;
m_uuid = uuid;
}
}
const QUuid &ConnectionConfig::uuid() const
{
return m_uuid;
}
void ConnectionConfig::setName(const QString& desc)
{
2022-05-26 08:25:31 +02:00
if (m_name != desc)
{
m_dirty = true;
m_name = std::move(desc);
}
}
const QString& ConnectionConfig::name() const
{
return m_name;
}
void ConnectionConfig::setHost(const QString& host)
{
2022-05-26 08:25:31 +02:00
if (m_host != host)
{
m_dirty = true;
m_host = std::move(host);
}
}
const QString& ConnectionConfig::host() const
{
return m_host;
}
void ConnectionConfig::setHostAddr(const QString &v)
{
2022-05-26 08:25:31 +02:00
if (m_hostaddr != v)
{
m_dirty = true;
m_hostaddr = std::move(v);
}
}
const QString& ConnectionConfig::hostAddr() const
{
return m_hostaddr;
}
void ConnectionConfig::setPort(unsigned short port)
{
2022-05-26 08:25:31 +02:00
if (m_port != port)
{
m_dirty = true;
m_port = port;
}
}
unsigned short ConnectionConfig::port() const
{
return m_port;
}
void ConnectionConfig::setUser(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_user != v)
{
m_dirty = true;
m_user = v;
}
}
const QString& ConnectionConfig::user() const
{
return m_user;
}
void ConnectionConfig::setPassword(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_password != v)
{
m_dirty = true;
m_password = v;
}
}
const QString& ConnectionConfig::password() const
{
return m_password;
}
void ConnectionConfig::setDbname(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_dbname != v)
{
m_dirty = true;
m_dbname = v;
}
}
const QString& ConnectionConfig::dbname() const
{
return m_dbname;
}
void ConnectionConfig::setSslMode(SslMode m)
{
2022-05-26 08:25:31 +02:00
if (m_sslMode != m)
{
m_dirty = true;
m_sslMode = m;
}
}
SslMode ConnectionConfig::sslMode() const
{
return m_sslMode;
}
void ConnectionConfig::setSslCert(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_sslCert != v)
{
m_dirty = true;
m_sslCert = std::move(v);
}
}
const QString& ConnectionConfig::sslCert() const
{
return m_sslCert;
}
void ConnectionConfig::setSslKey(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_sslKey != v)
{
m_dirty = true;
m_sslKey = std::move(v);
}
}
const QString& ConnectionConfig::sslKey() const
{
return m_sslKey;
}
void ConnectionConfig::setSslRootCert(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_sslRootCert != v)
{
m_dirty = true;
m_sslRootCert = std::move(v);
}
}
const QString& ConnectionConfig::sslRootCert() const
{
return m_sslRootCert;
}
void ConnectionConfig::setSslCrl(const QString& v)
{
2022-05-26 08:25:31 +02:00
if (m_sslCrl != v)
{
m_dirty = true;
m_sslCrl = std::move(v);
}
}
const QString& ConnectionConfig::sslCrl() const
{
return m_sslCrl;
}
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;
}
QString ConnectionConfig::makeLongDescription() const
{
QString result;
result = name() % " (" % user() % "@" % host() % ":" % QString::number(port()) % "/" % dbname() % ")";
return result;
}
const QByteArray& ConnectionConfig::encodedPassword() const
{
return m_encodedPassword;
}
void ConnectionConfig::setEncodedPassword(const QByteArray &encodedPassword)
{
m_dirty = true;
m_encodedPassword = encodedPassword;
}
QString ConnectionConfig::escapeConnectionStringValue(const QString &value)
{
bool contains_spaces = false;
int escapes = 0;
for (auto&& c : value)
2022-05-26 08:25:31 +02:00
if (c == ' ')
contains_spaces = true;
else if (c == '\'' || c == '\\')
++escapes;
2022-05-26 08:25:31 +02:00
if (contains_spaces || escapes > 0 || value.length() == 0)
{
QString result;
result.reserve(2 + value.length() + escapes);
result += '\'';
2022-05-26 08:25:31 +02:00
for (auto&& c : value)
{
if (c == '\'' || c == '\\')
result += '\\';
result += c;
}
result += '\'';
return result;
}
2022-05-26 08:25:31 +02:00
else
return value;
}
QString ConnectionConfig::connectionString() const
{
QString s;
s += "host="
% escapeConnectionStringValue(m_host)
% " port="
% QString::number(m_port)
% " user="
% escapeConnectionStringValue(m_user);
s += " password=";
s += escapeConnectionStringValue(m_password);
s += " dbname=";
s += escapeConnectionStringValue(m_dbname);
s += " sslmode=";
s += SslModeToString(m_sslMode);
2022-05-26 08:25:31 +02:00
if (!m_sslCert.isEmpty())
{
s += " sslcert=";
s += escapeConnectionStringValue(m_sslCert);
}
2022-05-26 08:25:31 +02:00
if (!m_sslKey.isEmpty())
{
s += " sslkey=";
s += escapeConnectionStringValue(m_sslKey);
}
2022-05-26 08:25:31 +02:00
if (!m_sslRootCert.isEmpty())
{
s += " sslrootcrt=";
s += escapeConnectionStringValue(m_sslRootCert);
}
2022-05-26 08:25:31 +02:00
if (!m_sslCrl.isEmpty())
{
s += " sslCrl=";
s += escapeConnectionStringValue(m_sslCrl);
}
s += " client_encoding=utf8";
s += " application_name=";
s += escapeConnectionStringValue(m_applicationName);
return s;
}
void ConnectionConfig::writeToEnvironment(QProcessEnvironment &env) const
{
strToEnv(env, "PGHOST", m_host);
strToEnv(env, "PGHOSTADDR", m_hostaddr);
strToEnv(env, "PGPORT", QString::number(m_port));
strToEnv(env, "PGDATABASE", m_dbname);
strToEnv(env, "PGUSER", m_user);
strToEnv(env, "PGPASSWORD", m_password);
strToEnv(env, "PGSSLMODE", SslModeToString(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 QString &val)
{
if (val.isEmpty())
env.remove(var);
else
env.insert(var, val);
}
void ConnectionGroup::erase(int idx, int count)
{
m_connections.remove(idx, count);
}
int ConnectionGroup::add(std::shared_ptr<ConnectionConfig> cc)
{
cc->setParent(this);
m_connections.push_back(cc);
return m_connections.size() - 1;
}
void ConnectionGroup::update(int idx, const ConnectionConfig &cc)
{
auto node = m_connections[idx];
*node = cc;
node->setParent(this);
}