File indexing completed on 2024-11-17 04:50:27
0001 /* 0002 kleo/keygroupconfig.cpp 0003 0004 This file is part of libkleopatra, the KDE keymanagement library 0005 SPDX-FileCopyrightText: 2021 g10 Code GmbH 0006 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include <config-libkleo.h> 0012 0013 #include "keygroupconfig.h" 0014 0015 #include "debug.h" 0016 #include "keygroup.h" 0017 0018 #include <libkleo/keycache.h> 0019 #include <libkleo/keyhelpers.h> 0020 #include <libkleo/qtstlhelpers.h> 0021 0022 #include <libkleo_debug.h> 0023 0024 #include <KConfigGroup> 0025 #include <KSharedConfig> 0026 0027 #include <QString> 0028 0029 #include <gpgme++/key.h> 0030 0031 using namespace Kleo; 0032 using namespace GpgME; 0033 0034 static const QString groupNamePrefix = QStringLiteral("Group-"); 0035 0036 class KeyGroupConfig::Private 0037 { 0038 public: 0039 explicit Private(const QString &filename); 0040 0041 std::vector<KeyGroup> readGroups() const; 0042 KeyGroup writeGroup(const KeyGroup &group); 0043 bool removeGroup(const KeyGroup &group); 0044 0045 private: 0046 KeyGroup readGroup(const KSharedConfigPtr &groupsConfig, const QString &groupId) const; 0047 0048 private: 0049 QString filename; 0050 }; 0051 0052 KeyGroupConfig::Private::Private(const QString &filename) 0053 : filename{filename} 0054 { 0055 if (filename.isEmpty()) { 0056 qCWarning(LIBKLEO_LOG) << __func__ << "Warning: name of configuration file is empty"; 0057 } 0058 } 0059 0060 KeyGroup KeyGroupConfig::Private::readGroup(const KSharedConfigPtr &groupsConfig, const QString &groupId) const 0061 { 0062 const KConfigGroup configGroup = groupsConfig->group(groupNamePrefix + groupId); 0063 0064 const QString groupName = configGroup.readEntry("Name", QString()); 0065 const auto fingerprints = toStdStrings(configGroup.readEntry("Keys", QStringList())); 0066 const std::vector<Key> groupKeys = KeyCache::instance()->findByFingerprint(fingerprints); 0067 0068 // treat group as immutable if any of its entries is immutable 0069 const QStringList entries = configGroup.keyList(); 0070 const bool isImmutable = (configGroup.isImmutable() // 0071 || std::any_of(entries.begin(), entries.end(), [configGroup](const QString &entry) { 0072 return configGroup.isEntryImmutable(entry); 0073 })); 0074 0075 KeyGroup g(groupId, groupName, groupKeys, KeyGroup::ApplicationConfig); 0076 g.setIsImmutable(isImmutable); 0077 qCDebug(LIBKLEO_LOG) << "Read group" << g; 0078 0079 return g; 0080 } 0081 0082 std::vector<KeyGroup> KeyGroupConfig::Private::readGroups() const 0083 { 0084 std::vector<KeyGroup> groups; 0085 0086 if (filename.isEmpty()) { 0087 return groups; 0088 } 0089 0090 const KSharedConfigPtr groupsConfig = KSharedConfig::openConfig(filename); 0091 const QStringList configGroups = groupsConfig->groupList(); 0092 for (const QString &configGroupName : configGroups) { 0093 qCDebug(LIBKLEO_LOG) << "Reading config group" << configGroupName; 0094 if (configGroupName.startsWith(groupNamePrefix)) { 0095 const QString keyGroupId = configGroupName.mid(groupNamePrefix.size()); 0096 if (keyGroupId.isEmpty()) { 0097 qCWarning(LIBKLEO_LOG) << "Config group" << configGroupName << "has empty group id"; 0098 continue; 0099 } 0100 KeyGroup group = readGroup(groupsConfig, keyGroupId); 0101 groups.push_back(group); 0102 } 0103 } 0104 0105 return groups; 0106 } 0107 0108 KeyGroup KeyGroupConfig::Private::writeGroup(const KeyGroup &group) 0109 { 0110 if (filename.isEmpty()) { 0111 return {}; 0112 } 0113 0114 if (group.isNull()) { 0115 qCDebug(LIBKLEO_LOG) << __func__ << "Error: group is null"; 0116 return group; 0117 } 0118 0119 KSharedConfigPtr groupsConfig = KSharedConfig::openConfig(filename); 0120 KConfigGroup configGroup = groupsConfig->group(groupNamePrefix + group.id()); 0121 0122 qCDebug(LIBKLEO_LOG) << __func__ << "Writing config group" << configGroup.name(); 0123 configGroup.writeEntry("Name", group.name()); 0124 configGroup.writeEntry("Keys", Kleo::getFingerprints(group.keys())); 0125 0126 // reread group to ensure that it reflects the saved group in case of immutable entries 0127 return readGroup(groupsConfig, group.id()); 0128 } 0129 0130 bool KeyGroupConfig::Private::removeGroup(const KeyGroup &group) 0131 { 0132 if (filename.isEmpty()) { 0133 return false; 0134 } 0135 0136 if (group.isNull()) { 0137 qCDebug(LIBKLEO_LOG) << __func__ << "Error: group is null"; 0138 return false; 0139 } 0140 0141 KSharedConfigPtr groupsConfig = KSharedConfig::openConfig(filename); 0142 KConfigGroup configGroup = groupsConfig->group(groupNamePrefix + group.id()); 0143 0144 qCDebug(LIBKLEO_LOG) << __func__ << "Removing config group" << configGroup.name(); 0145 configGroup.deleteGroup(QLatin1StringView()); 0146 0147 return true; 0148 } 0149 0150 KeyGroupConfig::KeyGroupConfig(const QString &filename) 0151 : d{std::make_unique<Private>(filename)} 0152 { 0153 } 0154 0155 KeyGroupConfig::~KeyGroupConfig() = default; 0156 0157 std::vector<KeyGroup> KeyGroupConfig::readGroups() const 0158 { 0159 return d->readGroups(); 0160 } 0161 0162 KeyGroup KeyGroupConfig::writeGroup(const KeyGroup &group) 0163 { 0164 return d->writeGroup(group); 0165 } 0166 0167 void KeyGroupConfig::writeGroups(const std::vector<KeyGroup> &groups) 0168 { 0169 std::for_each(std::begin(groups), std::end(groups), [this](const auto &group) { 0170 d->writeGroup(group); 0171 }); 0172 } 0173 0174 bool KeyGroupConfig::removeGroup(const KeyGroup &group) 0175 { 0176 return d->removeGroup(group); 0177 }