pgLab/pglablib/ConnectionConfig.cpp
eelke da19c46d5e Improve editing of connection password
Previously only a new password was saved if the save password checkbox was checked, Which always
started in the unchecked state. Now when editing existing connection the save password checkbox now
reflects if a password has been saved. Only when the password field is edited the program will update
the saved password. If the save password checkbox is unchecked then clear the save password.
2022-09-05 14:35:45 +02:00

401 lines
7.3 KiB
C++

#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)
{
for (auto e : SslModeStringTable)
if (e.mode == sm)
return QString::fromUtf8(e.string);
return {};
}
SslMode StringToSslMode(QString s)
{
SslMode result = SslMode::allow;
for (auto e : SslModeStringTable)
if (e.string == s)
result = e.mode;
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)
{
if (uuid != m_uuid)
{
m_dirty = true;
m_uuid = uuid;
}
}
const QUuid &ConnectionConfig::uuid() const
{
return m_uuid;
}
void ConnectionConfig::setName(const QString& desc)
{
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)
{
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)
{
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)
{
if (m_port != port)
{
m_dirty = true;
m_port = port;
}
}
unsigned short ConnectionConfig::port() const
{
return m_port;
}
void ConnectionConfig::setUser(const QString& v)
{
if (m_user != v)
{
m_dirty = true;
m_user = v;
}
}
const QString& ConnectionConfig::user() const
{
return m_user;
}
void ConnectionConfig::setPassword(const QString& v)
{
if (m_password != v)
{
m_dirty = true;
m_password = v;
}
}
const QString& ConnectionConfig::password() const
{
return m_password;
}
void ConnectionConfig::setDbname(const QString& v)
{
if (m_dbname != v)
{
m_dirty = true;
m_dbname = v;
}
}
const QString& ConnectionConfig::dbname() const
{
return m_dbname;
}
void ConnectionConfig::setSslMode(SslMode m)
{
if (m_sslMode != m)
{
m_dirty = true;
m_sslMode = m;
}
}
SslMode ConnectionConfig::sslMode() const
{
return m_sslMode;
}
void ConnectionConfig::setSslCert(const QString& v)
{
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)
{
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)
{
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)
{
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)
if (c == ' ')
contains_spaces = true;
else if (c == '\'' || c == '\\')
++escapes;
if (contains_spaces || escapes > 0 || value.length() == 0)
{
QString result;
result.reserve(2 + value.length() + escapes);
result += '\'';
for (auto&& c : value)
{
if (c == '\'' || c == '\\')
result += '\\';
result += c;
}
result += '\'';
return result;
}
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);
if (!m_sslCert.isEmpty())
{
s += " sslcert=";
s += escapeConnectionStringValue(m_sslCert);
}
if (!m_sslKey.isEmpty())
{
s += " sslkey=";
s += escapeConnectionStringValue(m_sslKey);
}
if (!m_sslRootCert.isEmpty())
{
s += " sslrootcrt=";
s += escapeConnectionStringValue(m_sslRootCert);
}
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);
}