File indexing completed on 2024-05-12 05:25:41

0001 /*
0002    SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "sieveeditorutil.h"
0008 #include "sieveeditor_debug.h"
0009 #include "sieveeditorsavepasswordjob.h"
0010 #include "sieveserversettings.h"
0011 
0012 #include <KConfig>
0013 
0014 #include <KConfigGroup>
0015 
0016 #include <KSharedConfig>
0017 #include <QRegularExpression>
0018 #include <QUrlQuery>
0019 
0020 #include <qt6keychain/keychain.h>
0021 using namespace QKeychain;
0022 
0023 QUrl SieveEditorUtil::SieveServerConfig::url() const
0024 {
0025     QUrl u;
0026     u.setHost(sieveSettings.serverName);
0027     u.setUserName(sieveSettings.userName);
0028     u.setPassword(sieveSettings.password);
0029     u.setPort(sieveSettings.port);
0030 
0031     QString authStr;
0032     switch (sieveSettings.authenticationType) {
0033     case MailTransport::Transport::EnumAuthenticationType::CLEAR:
0034     case MailTransport::Transport::EnumAuthenticationType::PLAIN:
0035         authStr = QStringLiteral("PLAIN");
0036         break;
0037     case MailTransport::Transport::EnumAuthenticationType::LOGIN:
0038         authStr = QStringLiteral("LOGIN");
0039         break;
0040     case MailTransport::Transport::EnumAuthenticationType::CRAM_MD5:
0041         authStr = QStringLiteral("CRAM-MD5");
0042         break;
0043     case MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5:
0044         authStr = QStringLiteral("DIGEST-MD5");
0045         break;
0046     case MailTransport::Transport::EnumAuthenticationType::GSSAPI:
0047         authStr = QStringLiteral("GSSAPI");
0048         break;
0049     case MailTransport::Transport::EnumAuthenticationType::ANONYMOUS:
0050         authStr = QStringLiteral("ANONYMOUS");
0051         break;
0052     default:
0053         authStr = QStringLiteral("PLAIN");
0054         break;
0055     }
0056     QUrlQuery query;
0057     query.addQueryItem(QStringLiteral("x-mech"), authStr);
0058     u.setQuery(query);
0059     return u;
0060 }
0061 
0062 bool SieveEditorUtil::SieveServerConfig::operator==(const SieveEditorUtil::SieveServerConfig &other) const
0063 {
0064     const bool result = (enabled == other.enabled) && (useImapCustomServer == other.useImapCustomServer) && (sieveSettings == other.sieveSettings)
0065         && (sieveImapAccountSettings == other.sieveImapAccountSettings);
0066     if (!result) {
0067         qCDebug(SIEVEEDITOR_LOG) << "enabled " << enabled << " other.enabled " << other.enabled;
0068         qCDebug(SIEVEEDITOR_LOG) << "useImapCustomServer " << useImapCustomServer << " other.useImapCustomServer " << other.useImapCustomServer;
0069         qCDebug(SIEVEEDITOR_LOG) << "sieveSettings " << sieveSettings << " other.sieveSettings " << other.sieveSettings;
0070         qCDebug(SIEVEEDITOR_LOG) << "sieveImapAccountSettings " << sieveImapAccountSettings << " other.sieveImapAccountSettings "
0071                                  << other.sieveImapAccountSettings;
0072     }
0073     return result;
0074 }
0075 
0076 void SieveEditorUtil::writeServerSieveConfig(const QList<SieveServerConfig> &lstConfig)
0077 {
0078     KSharedConfigPtr cfg = KSharedConfig::openConfig();
0079     const QRegularExpression re(QStringLiteral("^ServerSieve (.+)$"));
0080     // Delete Old Group
0081     const QStringList groups = cfg->groupList().filter(re);
0082     for (const QString &conf : groups) {
0083         KConfigGroup group = cfg->group(conf);
0084         group.deleteGroup();
0085     }
0086 
0087     int i = 0;
0088     for (const SieveEditorUtil::SieveServerConfig &conf : lstConfig) {
0089         writeSieveSettings(cfg, conf, i);
0090         ++i;
0091     }
0092     cfg->sync();
0093     cfg->reparseConfiguration();
0094 }
0095 
0096 QString SieveEditorUtil::sievePasswordIdentifier(const QString &userName, const QString &serverName)
0097 {
0098     return userName + QLatin1Char('@') + serverName;
0099 }
0100 
0101 QString SieveEditorUtil::imapPasswordIdentifier(const QString &userName, const QString &serverName)
0102 {
0103     return QLatin1StringView("Imap") + userName + QLatin1Char('@') + serverName;
0104 }
0105 
0106 void SieveEditorUtil::writeSieveSettings(const KSharedConfigPtr &cfg, const SieveEditorUtil::SieveServerConfig &conf, int index)
0107 {
0108     KConfigGroup group = cfg->group(QStringLiteral("ServerSieve %1").arg(index));
0109     group.writeEntry(QStringLiteral("Port"), conf.sieveSettings.port);
0110     group.writeEntry(QStringLiteral("ServerName"), conf.sieveSettings.serverName);
0111     group.writeEntry(QStringLiteral("UserName"), conf.sieveSettings.userName);
0112     group.writeEntry(QStringLiteral("Enabled"), conf.enabled);
0113 
0114     const QString walletEntry = SieveEditorUtil::sievePasswordIdentifier(conf.sieveSettings.userName, conf.sieveSettings.serverName);
0115     auto writeJob = new SieveEditorSavePasswordJob;
0116     writeJob->setName(SieveEditorUtil::walletFolderName());
0117     writeJob->setPassword(conf.sieveSettings.password);
0118     writeJob->setKey(walletEntry);
0119 
0120     writeJob->start();
0121 
0122     group.writeEntry(QStringLiteral("Authentication"), static_cast<int>(conf.sieveSettings.authenticationType));
0123 
0124     // Imap Account Settings
0125     group.writeEntry(QStringLiteral("ImapPort"), conf.sieveImapAccountSettings.port());
0126     group.writeEntry(QStringLiteral("ImapAuthentication"), static_cast<int>(conf.sieveImapAccountSettings.authenticationType()));
0127     group.writeEntry(QStringLiteral("ImapEncrypt"), static_cast<int>(conf.sieveImapAccountSettings.encryptionMode()));
0128 
0129     if ((conf.sieveImapAccountSettings.serverName() != conf.sieveSettings.serverName)
0130         && (conf.sieveImapAccountSettings.userName() != conf.sieveSettings.userName) && !conf.sieveImapAccountSettings.serverName().isEmpty()
0131         && !conf.sieveImapAccountSettings.userName().isEmpty()) {
0132         group.writeEntry(QStringLiteral("useImapCustomServer"), true);
0133         group.writeEntry(QStringLiteral("ImapServerName"), conf.sieveImapAccountSettings.serverName());
0134         group.writeEntry(QStringLiteral("ImapUserName"), conf.sieveImapAccountSettings.userName());
0135         const QString imapWalletEntry = imapPasswordIdentifier(conf.sieveImapAccountSettings.userName(), conf.sieveImapAccountSettings.serverName());
0136 
0137         auto writeImapSettingJob = new SieveEditorSavePasswordJob;
0138         writeImapSettingJob->setName(SieveEditorUtil::walletFolderName());
0139         writeImapSettingJob->setPassword(conf.sieveImapAccountSettings.password());
0140         writeImapSettingJob->setKey(imapWalletEntry);
0141         writeImapSettingJob->start();
0142     }
0143 }
0144 
0145 QString SieveEditorUtil::walletFolderName()
0146 {
0147     return QStringLiteral("sieveeditor");
0148 }
0149 
0150 void SieveEditorUtil::addServerSieveConfig(const SieveEditorUtil::SieveServerConfig &conf)
0151 {
0152     KSharedConfigPtr cfg = KSharedConfig::openConfig();
0153     const QRegularExpression re(QStringLiteral("^ServerSieve (.+)$"));
0154     const QStringList groups = cfg->groupList().filter(re);
0155 
0156     writeSieveSettings(cfg, conf, groups.count());
0157     cfg->sync();
0158 }
0159 
0160 QDebug operator<<(QDebug d, const SieveEditorUtil::SieveServerConfig &settings)
0161 {
0162     d << "sieveSettings " << settings.sieveSettings;
0163     d << "sieveImapAccountSettings " << settings.sieveImapAccountSettings;
0164     d << "url " << settings.url();
0165     d << "enabled " << settings.enabled;
0166     d << "useImapCustomServer " << settings.useImapCustomServer;
0167     return d;
0168 }
0169 
0170 QDebug operator<<(QDebug d, const SieveEditorUtil::SieveAccountSettings &settings)
0171 {
0172     d << "serverName " << settings.serverName;
0173     d << "userName " << settings.userName;
0174     d << "password " << settings.password;
0175     d << "authenticationType " << settings.authenticationType;
0176     d << "port " << settings.port;
0177     return d;
0178 }
0179 
0180 bool SieveEditorUtil::SieveAccountSettings::operator==(const SieveEditorUtil::SieveAccountSettings &other) const
0181 {
0182     bool result = (serverName == other.serverName) && (userName == other.userName) && (password == other.password)
0183         && (authenticationType == other.authenticationType) && (port == other.port);
0184     if (!result) {
0185         qCDebug(SIEVEEDITOR_LOG) << "serverName " << serverName << " other.serverName " << other.serverName;
0186         qCDebug(SIEVEEDITOR_LOG) << "userName " << userName << " other.userName " << other.userName;
0187         qCDebug(SIEVEEDITOR_LOG) << "password " << password << " other.password " << other.password;
0188         qCDebug(SIEVEEDITOR_LOG) << "authenticationType " << authenticationType << " other.authenticationType " << other.authenticationType;
0189         qCDebug(SIEVEEDITOR_LOG) << "port " << port << " other.port " << other.port;
0190     }
0191     return result;
0192 }
0193 
0194 bool SieveEditorUtil::SieveAccountSettings::isValid() const
0195 {
0196     return !serverName.isEmpty() && !userName.isEmpty() && (port != -1);
0197 }
0198 
0199 bool SieveEditorUtil::SieveServerConfig::isValid() const
0200 {
0201     return sieveSettings.isValid();
0202 }