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);
84 QList<QDBusObjectPath> items;
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)
106 prompt = QDBusObjectPath(
"/");
108 if (m_handle == -1) {
109 sendErrorReply(QStringLiteral(
"org.freedesktop.Secret.Error.IsLocked"),
110 QStringLiteral(
"Collection ") + fdoObjectPath().
path() + QStringLiteral(
" is locked"));
111 return QDBusObjectPath(
"/");
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)"));
117 return QDBusObjectPath(
"/");
119 if (!labelFound->canConvert<QString>()) {
120 sendErrorReply(QDBusError::ErrorType::InvalidArgs, QStringLiteral(
"Item label is not a string (org.freedesktop.Secret.Item.Label)"));
121 return QDBusObjectPath(
"/");
124 const QString fdoLabel = labelFound->toString();
126 QDBusObjectPath itemPath;
129 const auto attribsFound =
properties.map.find(QStringLiteral(
"org.freedesktop.Secret.Item.Attributes"));
130 if (attribsFound !=
properties.map.end() && attribsFound->canConvert<StrStrMap>()) {
131 attribs = attribsFound->
value<StrStrMap>();
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();
156 if (label.isEmpty()) {
157 sendErrorReply(QDBusError::ErrorType::InvalidArgs, QStringLiteral(
"Item label is invalid (org.freedesktop.Secret.Item.Label)"));
158 return QDBusObjectPath(
"/");
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());
175 return QDBusObjectPath(
"/");
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 const QString typeString = attribs.
value(QStringLiteral(
"type"));
186 if (typeString == QStringLiteral(
"map")) {
188 QMap<QString, QString>
map;
190 map[it.key()] = it.value().toString();
196 backend()->writeEntry(walletHandle(), dir, label, bytes, KWallet::Wallet::Map, FDO_APPID);
197 explicit_zero_mem(bytes.
data(), bytes.
size());
198 }
else if (xdgSchema == QStringLiteral(
"org.kde.KWallet.Password") || secret.mimeType.
startsWith(QStringLiteral(
"text/"))) {
199 auto bytes = decrypted.value.toByteArray();
201 backend()->writePassword(walletHandle(), dir, label, str, FDO_APPID);
202 explicit_zero_mem(bytes.
data(), bytes.
size());
203 explicit_zero_mem(str.data(), str.size() *
sizeof(QChar));
205 auto bytes = decrypted.value.toByteArray();
206 backend()->writeEntry(walletHandle(), dir, label, bytes, KWallet::Wallet::Stream, FDO_APPID);
207 explicit_zero_mem(bytes.
data(), bytes.
size());
211 onItemCreated(itemPath);
218 const auto name = walletName();
220 const QStringList aliases = fdoService()->readAliasesFor(name);
221 for (
const QString &alias : aliases) {
222 fdoService()->removeAlias(alias);
225 backend()->deleteWallet(name);
227 m_service->onCollectionDeleted(fdoObjectPath());
229 return QDBusObjectPath(
"/");
234 QList<QDBusObjectPath> result;
236 for (
const auto &entryLoc : m_itemAttribs.matchAttributes(attributes)) {
237 auto *itm = findItemByEntryLocation(entryLoc);
246int KWalletFreedesktopCollection::walletHandle()
const
251KWalletFreedesktopItem *KWalletFreedesktopCollection::getItemByObjectPath(
const QString &objectPath)
const
253 const auto found = m_items.find(objectPath);
254 if (found != m_items.end()) {
255 return found->second.get();
261KWalletFreedesktopItem *KWalletFreedesktopCollection::findItemByEntryLocation(
const EntryLocation &entryLocation)
const
263 const auto uniqLabel = FdoUniqueLabel::fromEntryLocation(entryLocation);
265 for (
const auto &itemPair : m_items) {
266 auto *item = itemPair.second.get();
267 if (item->uniqueLabel() == uniqLabel) {
275EntryLocation KWalletFreedesktopCollection::makeUniqueEntryLocation(
const QString &label)
280 if (slashPos == -1 || slashPos == label.size() - 1) {
281 dir = QStringLiteral(FDO_SECRETS_DEFAULT_DIR);
285 name = label.
mid(slashPos + 1);
289 QString resultName =
name;
290 while (backend()->hasEntry(m_handle, dir, resultName, FDO_APPID)) {
291 resultName = FdoUniqueLabel::makeName(name, suffix++);
294 return {
dir, resultName};
297FdoUniqueLabel KWalletFreedesktopCollection::makeUniqueItemLabel(
const QString &label)
299 return makeUniqueEntryLocation(label).toUniqueLabel();
302KWalletFreedesktopItem &KWalletFreedesktopCollection::pushNewItem(FdoUniqueLabel uniqLabel,
const QDBusObjectPath &path)
305 auto item = std::make_unique<KWalletFreedesktopItem>(
this, std::move(uniqLabel), path);
306 return *m_items.emplace(
path.path(), std::move(item)).first->second;
309KWalletFreedesktopItem &KWalletFreedesktopCollection::pushNewItem(
const QString &label,
const QDBusObjectPath &path)
311 return pushNewItem(makeUniqueItemLabel(label), path);
314KWalletFreedesktopService *KWalletFreedesktopCollection::fdoService()
const
319KSecretD *KWalletFreedesktopCollection::backend()
const
321 return fdoService()->backend();
329const FdoUniqueLabel &KWalletFreedesktopCollection::uniqueLabel()
const
331 return m_uniqueLabel;
334QString KWalletFreedesktopCollection::walletName()
const
336 return m_uniqueLabel.toName();
339void KWalletFreedesktopCollection::onWalletChangeState(
int handle)
341 if (handle == m_handle) {
347 if (handle >= 0 && m_handle >= 0) {
354 const QStringList folderList = backend()->folderList(m_handle, FDO_APPID);
355 for (
const QString &folder : folderList) {
356 const QStringList entries = backend()->entryList(m_handle, folder, FDO_APPID);
359 for (
const auto &entry : entries) {
360 const EntryLocation entryLoc{folder, entry};
361 const auto itm = findItemByEntryLocation(entryLoc);
364 attr[
"server"] = folder;
365 attr[
"user"] = entry;
366 switch (backend()->entryType(m_handle, folder, entry, FDO_APPID)) {
367 case KWallet::Wallet::Stream:
368 attr[
"type"] =
"binary";
370 case KWallet::Wallet::Map:
371 attr[
"type"] =
"map";
373 case KWallet::Wallet::Password:
375 attr[
"type"] =
"plaintext";
378 itemAttributes().newItem(entryLoc);
379 itemAttributes().setParam(entryLoc, FDO_KEY_CREATED, createTime);
380 itemAttributes().setParam(entryLoc, FDO_KEY_MODIFIED, createTime);
381 itemAttributes().setAttributes(entryLoc, attr);
382 auto &newItem = pushNewItem(entryLoc.toUniqueLabel(), nextItemPath());
383 newItem.setAttributes(attr);
384 Q_EMIT ItemCreated(newItem.fdoObjectPath());
386 Q_EMIT ItemChanged(itm->fdoObjectPath());
392void KWalletFreedesktopCollection::onItemCreated(
const QDBusObjectPath &item)
394 itemAttributes().updateLastModified();
399 onPropertiesChanged(props);
402void KWalletFreedesktopCollection::onItemChanged(
const QDBusObjectPath &item)
404 itemAttributes().updateLastModified();
408void KWalletFreedesktopCollection::onItemDeleted(
const QDBusObjectPath &item)
410 itemAttributes().updateLastModified();
411 const auto itemMapPos = m_items.find(item.
path());
412 if (itemMapPos == m_items.end()) {
415 auto *itemPtr = itemMapPos->second.get();
420 itemPtr->setDeleted();
421 itemPtr->deleteLater();
422 itemMapPos->second.release();
423 m_items.erase(itemMapPos);
429 onPropertiesChanged(props);
432void KWalletFreedesktopCollection::onPropertiesChanged(
const QVariantMap &properties)
434 auto msg =
QDBusMessage::createSignal(fdoObjectPath().
path(), QStringLiteral(
"org.freedesktop.DBus.Properties"), QStringLiteral(
"PropertiesChanged"));
435 auto args = QVariantList();
436 args << QStringLiteral(
"org.freedesktop.Secret.Collection") <<
properties << QStringList();
437 msg.setArguments(args);
441KWalletFreedesktopAttributes &KWalletFreedesktopCollection::itemAttributes()
443 return m_itemAttribs;
446const KWalletFreedesktopAttributes &KWalletFreedesktopCollection::itemAttributes()
const
448 return m_itemAttribs;
451#include "moc_kwalletfreedesktopcollection.cpp"
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 name(StandardAction id)
qsizetype size() const const
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
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QJsonObject object() const const
const_iterator constBegin() const const
const_iterator constEnd() const const
void push_back(parameter_type value)
iterator find(const Key &key)
T value(const Key &key, const T &defaultValue) const const
iterator erase(const_iterator first, const_iterator last)
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)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QVariant fromValue(T &&value)