#include "settings.h" #include #include #include namespace { const QLatin1String kService("photogallery-uploader"); const QLatin1String kPasswordKey("password"); } // namespace Settings::Settings() : m_settings(QStringLiteral("inflo.ws"), QStringLiteral("photogallery-uploader")) { } QString Settings::baseUrl() const { return m_settings.value(QStringLiteral("baseUrl")).toString(); } void Settings::setBaseUrl(const QString &value) { m_settings.setValue(QStringLiteral("baseUrl"), normalizeBaseUrl(value)); } QString Settings::username() const { return m_settings.value(QStringLiteral("username")).toString(); } void Settings::setUsername(const QString &value) { m_settings.setValue(QStringLiteral("username"), value.trimmed()); } QString Settings::readPassword() const { QKeychain::ReadPasswordJob job(kService); job.setAutoDelete(false); job.setKey(kPasswordKey); QEventLoop loop; QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); loop.exec(); if (job.error() != QKeychain::NoError) return QString(); return job.textData(); } void Settings::writePassword(const QString &value) const { QKeychain::WritePasswordJob job(kService); job.setAutoDelete(false); job.setKey(kPasswordKey); job.setTextData(value); QEventLoop loop; QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); loop.exec(); } bool Settings::isConfigured() const { return !baseUrl().isEmpty() && !username().isEmpty() && !readPassword().isEmpty(); } Settings::LastPost Settings::lastPost() const { LastPost p; p.slug = m_settings.value(QStringLiteral("last/slug")).toString(); p.url = m_settings.value(QStringLiteral("last/url")).toString(); p.caption = m_settings.value(QStringLiteral("last/caption")).toString(); p.postedAt = m_settings.value(QStringLiteral("last/postedAt")).toDateTime(); return p; } void Settings::setLastPost(const LastPost &value) { m_settings.setValue(QStringLiteral("last/slug"), value.slug); m_settings.setValue(QStringLiteral("last/url"), value.url); m_settings.setValue(QStringLiteral("last/caption"), value.caption); m_settings.setValue(QStringLiteral("last/postedAt"), value.postedAt); } QString Settings::validateBaseUrl(const QString &raw) { const QString trimmed = raw.trimmed(); if (trimmed.isEmpty()) return QStringLiteral("Base URL is required"); const QUrl url(trimmed); if (!url.isValid() || url.host().isEmpty()) return QStringLiteral("Not a valid URL"); if (url.scheme() != QStringLiteral("https")) return QStringLiteral("Must be https — plain http sends your password in the clear"); return QString(); } QString Settings::normalizeBaseUrl(const QString &raw) { QString v = raw.trimmed(); while (v.endsWith(QLatin1Char('/'))) v.chop(1); if (v.endsWith(QStringLiteral("/upload"), Qt::CaseInsensitive)) v.chop(QStringLiteral("/upload").size()); while (v.endsWith(QLatin1Char('/'))) v.chop(1); return v; }