7#include "kwalletfreedesktopcollection.h"
10#include "kwalletfreedesktopcollectionadaptor.h"
11#include "kwalletfreedesktopitem.h"
13KWalletFreedesktopCollection::KWalletFreedesktopCollection(KWalletFreedesktopService *service,
19 , m_uniqueLabel(FdoUniqueLabel::fromName(walletName))
20 , m_objectPath(std::
move(objectPath))
21 , m_itemAttribs(walletName)
23 (void)
new KWalletFreedesktopCollectionAdaptor(
this);
26 const QStringList aliases = fdoService()->readAliasesFor(walletName);
27 for (
const auto &alias : aliases) {
31 onWalletChangeState(handle);
35 const auto items = itemAttributes().listItems();
36 for (
const auto &entryLocation : items) {
37 if (!findItemByEntryLocation(entryLocation)) {
38 pushNewItem(entryLocation.toUniqueLabel(), nextItemPath());
49const QString &KWalletFreedesktopCollection::label()
const
51 return m_uniqueLabel.label;
54void KWalletFreedesktopCollection::setLabel(
const QString &newLabel)
56 if (newLabel == label()) {
60 const auto oldName = m_uniqueLabel.toName();
61 const auto newUniqLabel = fdoService()->makeUniqueCollectionLabel(newLabel);
62 const auto newName = newUniqLabel.toName();
64 int rc = backend()->renameWallet(oldName, newName);
66 const QStringList aliases = fdoService()->readAliasesFor(walletName());
67 m_uniqueLabel = newUniqLabel;
68 const QString newName = walletName();
69 for (
const auto &alias : aliases) {
70 fdoService()->updateCollectionAlias(alias, newName);
73 itemAttributes().renameWallet(newName);
77bool KWalletFreedesktopCollection::locked()
const
79 return m_handle < 0 || !backend()->isOpen(m_handle);
86 for (
const auto &item : m_items) {
87 items.
push_back(item.second->fdoObjectPath());
93qulonglong KWalletFreedesktopCollection::created()
const
95 return itemAttributes().birthTime();
98qulonglong KWalletFreedesktopCollection::modified()
const
100 return itemAttributes().lastModified();
104KWalletFreedesktopCollection::CreateItem(
const PropertiesMap &properties,
const FreedesktopSecret &secret,
bool replace,
QDBusObjectPath &prompt)
108 if (m_handle == -1) {
109 sendErrorReply(QStringLiteral(
"org.freedesktop.Secret.Error.IsLocked"),
110 QStringLiteral(
"Collection ") + fdoObjectPath().
path() + QStringLiteral(
" is locked"));
114 const auto labelFound =
properties.map.find(QStringLiteral(
"org.freedesktop.Secret.Item.Label"));
116 sendErrorReply(QDBusError::ErrorType::InvalidArgs, QStringLiteral(
"Item label is missing (org.freedesktop.Secret.Item.Label)"));
119 if (!labelFound->canConvert<
QString>()) {
120 sendErrorReply(QDBusError::ErrorType::InvalidArgs, QStringLiteral(
"Item label is not a string (org.freedesktop.Secret.Item.Label)"));
124 const QString fdoLabel = labelFound->toString();
129 const auto attribsFound =
properties.map.find(QStringLiteral(
"org.freedesktop.Secret.Item.Attributes"));
136 const auto matchedItems = itemAttributes().matchAttributes(attribs);
138 if (!matchedItems.empty()) {
139 const auto &entryLoc = matchedItems.constFirst();
140 const auto item = findItemByEntryLocation(entryLoc);
142 itemPath = item->fdoObjectPath();
143 dir = entryLoc.folder;
144 label = entryLoc.key;
150 const auto entryLocation = makeUniqueEntryLocation(fdoLabel);
151 dir = entryLocation.folder;
152 label = entryLocation.key;
153 itemPath = nextItemPath();
157 sendErrorReply(QDBusError::ErrorType::InvalidArgs, QStringLiteral(
"Item label is invalid (org.freedesktop.Secret.Item.Label)"));
162 const EntryLocation entryLoc{
dir,
label};
163 itemAttributes().newItem(entryLoc);
164 itemAttributes().setParam(entryLoc, FDO_KEY_MIME, secret.mimeType);
165 itemAttributes().setParam(entryLoc, FDO_KEY_CREATED, createTime);
166 itemAttributes().setParam(entryLoc, FDO_KEY_MODIFIED, createTime);
167 itemAttributes().setAttributes(entryLoc, attribs);
169 pushNewItem(entryLoc.toUniqueLabel(), itemPath);
172 auto decrypted = secret;
173 if (!fdoService()->desecret(
message(), decrypted)) {
174 sendErrorReply(QDBusError::ErrorType::InvalidObjectPath, QStringLiteral(
"Can't find session ") + secret.session.
path());
178 QString xdgSchema = QStringLiteral(
"org.kde.KWallet.Stream");
179 const auto found = attribs.
find(FDO_KEY_XDG_SCHEMA);
180 if (found != attribs.
end()) {
181 xdgSchema = found.value();
184 if (xdgSchema == QStringLiteral(
"org.kde.KWallet.Password") || secret.mimeType.
startsWith(QStringLiteral(
"text/"))) {
185 auto bytes = decrypted.value.toByteArray();
187 backend()->writePassword(walletHandle(), dir, label, str, FDO_APPID);
188 explicit_zero_mem(bytes.data(), bytes.size());
189 explicit_zero_mem(str.data(), str.size() *
sizeof(
QChar));
191 auto bytes = decrypted.value.toByteArray();
192 backend()->writeEntry(walletHandle(), dir, label, bytes, KWallet::Wallet::Stream, FDO_APPID);
193 explicit_zero_mem(bytes.data(), bytes.size());
197 onItemCreated(itemPath);
204 const auto name = walletName();
206 const QStringList aliases = fdoService()->readAliasesFor(name);
207 for (
const QString &alias : aliases) {
208 fdoService()->removeAlias(alias);
211 backend()->deleteWallet(name);
213 m_service->onCollectionDeleted(fdoObjectPath());
222 for (
const auto &entryLoc : m_itemAttribs.matchAttributes(attributes)) {
223 auto *itm = findItemByEntryLocation(entryLoc);
232int KWalletFreedesktopCollection::walletHandle()
const
237KWalletFreedesktopItem *KWalletFreedesktopCollection::getItemByObjectPath(
const QString &objectPath)
const
239 const auto found = m_items.find(objectPath);
240 if (found != m_items.end()) {
241 return found->second.get();
247KWalletFreedesktopItem *KWalletFreedesktopCollection::findItemByEntryLocation(
const EntryLocation &entryLocation)
const
249 const auto uniqLabel = FdoUniqueLabel::fromEntryLocation(entryLocation);
251 for (
const auto &itemPair : m_items) {
252 auto *item = itemPair.second.get();
253 if (item->uniqueLabel() == uniqLabel) {
261EntryLocation KWalletFreedesktopCollection::makeUniqueEntryLocation(
const QString &label)
266 if (slashPos == -1 || slashPos ==
label.
size() - 1) {
267 dir = QStringLiteral(FDO_SECRETS_DEFAULT_DIR);
276 while (backend()->hasEntry(m_handle, dir, resultName, FDO_APPID)) {
277 resultName = FdoUniqueLabel::makeName(name, suffix++);
280 return {
dir, resultName};
283FdoUniqueLabel KWalletFreedesktopCollection::makeUniqueItemLabel(
const QString &label)
285 return makeUniqueEntryLocation(label).toUniqueLabel();
288KWalletFreedesktopItem &KWalletFreedesktopCollection::pushNewItem(FdoUniqueLabel uniqLabel,
const QDBusObjectPath &path)
290 m_items.erase(
path.path());
291 auto item = std::make_unique<KWalletFreedesktopItem>(
this, std::move(uniqLabel), path);
292 return *m_items.emplace(
path.path(), std::move(item)).first->second;
295KWalletFreedesktopItem &KWalletFreedesktopCollection::pushNewItem(
const QString &label,
const QDBusObjectPath &path)
297 return pushNewItem(makeUniqueItemLabel(label), path);
300KWalletFreedesktopService *KWalletFreedesktopCollection::fdoService()
const
305KWalletD *KWalletFreedesktopCollection::backend()
const
307 return fdoService()->backend();
315const FdoUniqueLabel &KWalletFreedesktopCollection::uniqueLabel()
const
317 return m_uniqueLabel;
320QString KWalletFreedesktopCollection::walletName()
const
322 return m_uniqueLabel.toName();
325void KWalletFreedesktopCollection::onWalletChangeState(
int handle)
327 if (handle == m_handle) {
331 if (handle >= 0 && m_handle >= 0) {
338 if (m_handle < 0 || !m_items.empty()) {
342 const QStringList folderList = backend()->folderList(m_handle, FDO_APPID);
343 for (
const QString &folder : folderList) {
344 const QStringList entries = backend()->entryList(m_handle, folder, FDO_APPID);
346 for (
const auto &entry : entries) {
347 const EntryLocation entryLoc{folder, entry};
348 const auto itm = findItemByEntryLocation(entryLoc);
350 auto &newItem = pushNewItem(entryLoc.toUniqueLabel(), nextItemPath());
351 Q_EMIT ItemChanged(newItem.fdoObjectPath());
353 Q_EMIT ItemChanged(itm->fdoObjectPath());
359void KWalletFreedesktopCollection::onItemCreated(
const QDBusObjectPath &item)
361 itemAttributes().updateLastModified();
366 onPropertiesChanged(props);
369void KWalletFreedesktopCollection::onItemChanged(
const QDBusObjectPath &item)
371 itemAttributes().updateLastModified();
375void KWalletFreedesktopCollection::onItemDeleted(
const QDBusObjectPath &item)
377 itemAttributes().updateLastModified();
378 const auto itemMapPos = m_items.find(item.
path());
379 if (itemMapPos == m_items.end()) {
382 auto *itemPtr = itemMapPos->second.get();
387 itemPtr->setDeleted();
388 itemPtr->deleteLater();
389 itemMapPos->second.release();
390 m_items.erase(itemMapPos);
396 onPropertiesChanged(props);
399void KWalletFreedesktopCollection::onPropertiesChanged(
const QVariantMap &properties)
401 auto msg =
QDBusMessage::createSignal(fdoObjectPath().
path(), QStringLiteral(
"org.freedesktop.DBus.Properties"), QStringLiteral(
"PropertiesChanged"));
402 auto args = QVariantList();
404 msg.setArguments(args);
408KWalletFreedesktopAttributes &KWalletFreedesktopCollection::itemAttributes()
410 return m_itemAttribs;
413const KWalletFreedesktopAttributes &KWalletFreedesktopCollection::itemAttributes()
const
415 return m_itemAttribs;
418#include "moc_kwalletfreedesktopcollection.cpp"
QString name(GameStandardAction id)
KIOCORE_EXPORT CopyJob * move(const QList< QUrl > &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
QString label(StandardShortcut id)
qint64 currentSecsSinceEpoch()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
bool send(const QDBusMessage &message) const const
QDBusConnection sessionBus()
void unregisterObject(const QString &path, UnregisterMode mode)
const QDBusMessage & message() const const
void sendErrorReply(QDBusError::ErrorType type, const QString &msg) const const
QDBusMessage createSignal(const QString &path, const QString &interface, const QString &name)
QString path() const const
void push_back(parameter_type value)
iterator find(const Key &key)
T value(const Key &key, const T &defaultValue) const const
QString fromUtf8(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QVariant fromValue(T &&value)