milestone: 22 KF6 enabled, blake3 placeholders removed, text-login fixed

- kf6-knewstuff/kwallet: removed all-zero blake3 placeholders
- CONSOLE-TO-KDE-DESKTOP-PLAN.md: 20→22 KF6 enabled count
- BOOT-PROCESS-IMPROVEMENT-PLAN.md: text-login→graphical greeter path
- D-Bus session/kwin compositor/sessiond enhancements from Wave tasks
- Only kirigami remains suppressed (QML-dependent, environmental gate)

Zero warnings. 24 commits total.
This commit is contained in:
2026-04-29 14:48:47 +01:00
parent cb2e75e640
commit edb68153e3
621 changed files with 1034826 additions and 223 deletions
@@ -0,0 +1,2 @@
add_subdirectory(KWallet)
@@ -0,0 +1,161 @@
include(ECMGenerateHeaders)
ecm_setup_version(${KF_VERSION} VARIABLE_PREFIX KWALLET
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kwallet_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF6WalletConfigVersion.cmake"
SOVERSION 6)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kwallet_version.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KWallet COMPONENT Devel
)
if(APPLE)
option(MAC_USE_OSXKEYCHAIN "On OS X, use the keychain as backend for kwallet, instead of kwalletd.")
else()
set(MAC_USE_OSXKEYCHAIN FALSE)
endif()
add_library(KF6Wallet)
add_library(KF6::Wallet ALIAS KF6Wallet)
set_target_properties(KF6Wallet PROPERTIES
VERSION ${KWALLET_VERSION}
SOVERSION ${KWALLET_SOVERSION}
EXPORT_NAME Wallet
)
if (MAC_USE_OSXKEYCHAIN)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
find_library(SECURITY_LIBRARY Security)
target_sources(KF6Wallet PRIVATE
kwallet_mac.cpp
)
else()
set(kwallet_dbus_SRCS)
if (NOT EXCLUDE_DEPRECATED_BEFORE_AND_AT STREQUAL "CURRENT" AND
EXCLUDE_DEPRECATED_BEFORE_AND_AT VERSION_LESS 5.72.0)
set(kwallet_xml org.kde.KWallet.xml)
else()
# copy of org.kde.KWallet.xml, but with all deprecated API removed
set(kwallet_xml org.kde.KWallet.nodeprecated.xml)
endif()
qt_add_dbus_interface(kwallet_dbus_SRCS ${kwallet_xml} kwallet_interface)
target_sources(KF6Wallet PRIVATE
kwallet.cpp
${kwallet_dbus_SRCS}
)
endif()
ecm_qt_declare_logging_category(KF6Wallet
HEADER kwallet_api_debug.h
IDENTIFIER KWALLET_API_LOG
CATEGORY_NAME kf.wallet.api
OLD_CATEGORY_NAMES kf5.kwallet.api
DESCRIPTION "kwallet api"
EXPORT KWALLET
)
ecm_generate_export_header(KF6Wallet
BASE_NAME KWallet
GROUP_BASE_NAME KF
VERSION ${KF_VERSION}
USE_VERSION_HEADER
DEPRECATED_BASE_VERSION 0
DEPRECATION_VERSIONS 5.72
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
)
target_include_directories(KF6Wallet INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KWallet>")
target_link_libraries(KF6Wallet
PUBLIC
Qt6::Gui
PRIVATE
Qt6::DBus
Qt6::Widgets
KF6::ConfigCore # used to store the wallet to be used
)
if(MAC_USE_OSXKEYCHAIN)
target_link_libraries(KF6Wallet PRIVATE ${CARBON_LIBRARY}
${SECURITY_LIBRARY}
${COREFOUNDATION_LIBRARY})
elseif(APPLE)
target_link_libraries(KF6Wallet PRIVATE ${CARBON_LIBRARY})
else()
target_link_libraries(KF6Wallet PRIVATE Qt6::DBus)
install(FILES ${kwallet_xml} DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} RENAME kf6_org.kde.KWallet.xml)
endif()
ecm_generate_headers(KWallet_HEADERS
HEADER_NAMES
KWallet
REQUIRED_HEADERS KWallet_HEADERS
)
install(TARGETS KF6Wallet EXPORT KF6WalletTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/kwallet_export.h
${KWallet_HEADERS}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KWallet COMPONENT Devel
)
if(BUILD_QCH)
ecm_add_qch(
KF6Wallet_QCH
NAME KWallet
BASE_NAME KF6Wallet
VERSION ${KF_VERSION}
ORG_DOMAIN org.kde
SOURCES # using only public headers, to cover only public API
${KWallet_HEADERS}
LINK_QCHS
Qt6Gui_QCH
INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}
BLANK_MACROS
KWALLET_EXPORT
KWALLET_DEPRECATED
KWALLET_DEPRECATED_EXPORT
"KWALLET_DEPRECATED_VERSION(x, y, t)"
TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
COMPONENT Devel
)
endif()
# create a Config.cmake and a ConfigVersion.cmake file and install them
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF6Wallet")
if (BUILD_QCH)
ecm_install_qch_export(
TARGETS KF6Wallet_QCH
FILE KF6WalletQchTargets.cmake
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
COMPONENT Devel
)
set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF6WalletQchTargets.cmake\")")
endif()
include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/KF6WalletConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/KF6WalletConfig.cmake"
PATH_VARS KDE_INSTALL_DBUSINTERFACEDIR
PATH_VARS KDE_INSTALL_BINDIR
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/KF6WalletConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/KF6WalletConfigVersion.cmake"
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
COMPONENT Devel
)
install(EXPORT KF6WalletTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF6WalletTargets.cmake NAMESPACE KF6:: )
@@ -0,0 +1,10 @@
@PACKAGE_INIT@
set(KWALLET_DBUS_INTERFACES_DIR "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@")
set(KWALLETD_BIN_PATH "@PACKAGE_KDE_INSTALL_BINDIR@/kwalletd6")
include(CMakeFindDependencyMacro)
find_dependency(Qt6Gui @REQUIRED_QT_VERSION@)
include("${CMAKE_CURRENT_LIST_DIR}/KF6WalletTargets.cmake")
@PACKAGE_INCLUDE_QCHTARGETS@
@@ -0,0 +1,931 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2002-2004 George Staikos <staikos@kde.org>
SPDX-FileCopyrightText: 2008 Michael Leupold <lemma@confuego.org>
SPDX-FileCopyrightText: 2011 Valentin Rusu <kde@rusu.info>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kwallet.h"
#include "kwallet_api_debug.h"
#include <QApplication>
#include <QDBusConnection>
#include <QRegularExpression>
#include <KConfigGroup>
#include <KSharedConfig>
#include "kwallet_interface.h"
typedef QMap<QString, QByteArray> StringByteArrayMap;
Q_DECLARE_METATYPE(StringByteArrayMap)
namespace KWallet
{
class KWalletDLauncher
{
public:
KWalletDLauncher();
~KWalletDLauncher();
KWalletDLauncher(const KWalletDLauncher &) = delete;
KWalletDLauncher &operator=(const KWalletDLauncher &) = delete;
org::kde::KWallet &getInterface();
org::kde::KWallet *m_wallet_deamon;
KConfigGroup m_cgroup;
bool m_walletEnabled;
};
Q_GLOBAL_STATIC(KWalletDLauncher, walletLauncher)
static QString appid()
{
return qApp->applicationName();
}
static void registerTypes()
{
static bool registered = false;
if (!registered) {
qDBusRegisterMetaType<StringByteArrayMap>();
registered = true;
}
}
const QString Wallet::LocalWallet()
{
KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group(QStringLiteral("Wallet")));
if (!cfg.readEntry("Use One Wallet", true)) {
QString tmp = cfg.readEntry("Local Wallet", "localwallet");
if (tmp.isEmpty()) {
return QStringLiteral("localwallet");
}
return tmp;
}
QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
if (tmp.isEmpty()) {
return QStringLiteral("kdewallet");
}
return tmp;
}
const QString Wallet::NetworkWallet()
{
KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group(QStringLiteral("Wallet")));
QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
if (tmp.isEmpty()) {
return QStringLiteral("kdewallet");
}
return tmp;
}
const QString Wallet::PasswordFolder()
{
return QStringLiteral("Passwords");
}
const QString Wallet::FormDataFolder()
{
return QStringLiteral("Form Data");
}
class Q_DECL_HIDDEN Wallet::WalletPrivate
{
public:
WalletPrivate(Wallet *wallet, int h, const QString &n)
: q(wallet)
, name(n)
, handle(h)
{
}
void walletServiceUnregistered();
Wallet *q;
QString name;
QString folder;
int handle;
int transactionId;
};
static const char s_kwalletdServiceName[] = "org.kde.kwalletd6";
Wallet::Wallet(int handle, const QString &name)
: QObject(nullptr)
, d(new WalletPrivate(this, handle, name))
{
QDBusServiceWatcher *watcher =
new QDBusServiceWatcher(QString::fromLatin1(s_kwalletdServiceName), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration, this);
connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, [this]() {
d->walletServiceUnregistered();
});
connect(&walletLauncher()->getInterface(), &org::kde::KWallet::walletClosedId, this, &KWallet::Wallet::slotWalletClosed);
connect(&walletLauncher()->getInterface(), &org::kde::KWallet::folderListUpdated, this, &KWallet::Wallet::slotFolderListUpdated);
connect(&walletLauncher()->getInterface(), &org::kde::KWallet::folderUpdated, this, &KWallet::Wallet::slotFolderUpdated);
connect(&walletLauncher()->getInterface(), &org::kde::KWallet::applicationDisconnected, this, &KWallet::Wallet::slotApplicationDisconnected);
// Verify that the wallet is still open
if (d->handle != -1) {
QDBusReply<bool> r = walletLauncher()->getInterface().isOpen(d->handle);
if (r.isValid() && !r) {
d->handle = -1;
d->name.clear();
}
}
}
Wallet::~Wallet()
{
if (d->handle != -1) {
if (!walletLauncher.isDestroyed()) {
walletLauncher()->getInterface().close(d->handle, false, appid());
} else {
qCDebug(KWALLET_API_LOG) << "Problem with static destruction sequence."
"Destroy any static Wallet before the event-loop exits.";
}
d->handle = -1;
d->folder.clear();
d->name.clear();
}
delete d;
}
QStringList Wallet::walletList()
{
QStringList result;
if (walletLauncher()->m_walletEnabled) {
QDBusReply<QStringList> r = walletLauncher()->getInterface().wallets();
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
} else {
result = r;
}
}
return result;
}
void Wallet::changePassword(const QString &name, WId w)
{
if (w == 0) {
qCDebug(KWALLET_API_LOG) << "Pass a valid window to KWallet::Wallet::changePassword().";
}
if (walletLauncher()->m_walletEnabled) {
walletLauncher()->getInterface().changePassword(name, (qlonglong)w, appid());
}
}
bool Wallet::isEnabled()
{
return walletLauncher()->m_walletEnabled;
}
bool Wallet::isOpen(const QString &name)
{
if (walletLauncher()->m_walletEnabled) {
QDBusReply<bool> r = walletLauncher()->getInterface().isOpen(name);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
} else {
return false;
}
}
int Wallet::closeWallet(const QString &name, bool force)
{
if (walletLauncher()->m_walletEnabled) {
QDBusReply<int> r = walletLauncher()->getInterface().close(name, force);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return -1;
} else {
return r;
}
} else {
return -1;
}
}
int Wallet::deleteWallet(const QString &name)
{
if (walletLauncher->m_walletEnabled) {
QDBusReply<int> r = walletLauncher()->getInterface().deleteWallet(name);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return -1;
} else {
return r;
}
} else {
return -1;
}
}
Wallet *Wallet::openWallet(const QString &name, WId w, OpenType ot)
{
if (w == 0) {
qCDebug(KWALLET_API_LOG) << "Pass a valid window to KWallet::Wallet::openWallet().";
}
if (!walletLauncher()->m_walletEnabled) {
qCDebug(KWALLET_API_LOG) << "User disabled the wallet system so returning 0 here.";
return nullptr;
}
Wallet *wallet = new Wallet(-1, name);
// connect the daemon's opened signal to the slot filtering the
// signals we need
connect(&walletLauncher()->getInterface(), &org::kde::KWallet::walletAsyncOpened, wallet, &KWallet::Wallet::walletAsyncOpened);
org::kde::KWallet &interface = walletLauncher->getInterface();
// do the call
QDBusReply<int> r;
if (ot == Synchronous) {
interface.setTimeout(0x7FFFFFFF); // Don't timeout after 25s, but 24 days
r = interface.open(name, (qlonglong)w, appid());
interface.setTimeout(-1); // Back to the default 25s
// after this call, r would contain a transaction id >0 if OK or -1 if NOK
// if OK, the slot walletAsyncOpened should have been received, but the transaction id
// will not match. We'll get that handle from the reply - see below
} else if (ot == Asynchronous) {
r = interface.openAsync(name, (qlonglong)w, appid(), true);
} else if (ot == Path) {
r = interface.openPathAsync(name, (qlonglong)w, appid(), true);
} else {
delete wallet;
return nullptr;
}
// error communicating with the daemon (maybe not running)
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
delete wallet;
return nullptr;
}
wallet->d->transactionId = r.value();
if (ot == Synchronous || ot == Path) {
// check for an immediate error
if (wallet->d->transactionId < 0) {
delete wallet;
wallet = nullptr;
} else {
wallet->d->handle = r.value();
}
} else if (ot == Asynchronous) {
if (wallet->d->transactionId < 0) {
QTimer::singleShot(0, wallet, SLOT(emitWalletAsyncOpenError()));
// client code is responsible for deleting the wallet
}
}
return wallet;
}
void Wallet::slotCollectionStatusChanged(int status)
{
Q_UNUSED(status)
}
void Wallet::slotCollectionDeleted()
{
d->folder.clear();
d->name.clear();
Q_EMIT walletClosed();
}
bool Wallet::disconnectApplication(const QString &wallet, const QString &app)
{
if (walletLauncher()->m_walletEnabled) {
QDBusReply<bool> r = walletLauncher()->getInterface().disconnectApplication(wallet, app);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
} else {
return true;
}
}
QStringList Wallet::users(const QString &name)
{
if (walletLauncher()->m_walletEnabled) {
QDBusReply<QStringList> r = walletLauncher()->getInterface().users(name);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return QStringList();
} else {
return r;
}
} else {
return QStringList();
}
}
int Wallet::sync()
{
if (d->handle == -1) {
return -1;
}
walletLauncher()->getInterface().sync(d->handle, appid());
return 0;
}
int Wallet::lockWallet()
{
if (d->handle == -1) {
return -1;
}
QDBusReply<int> r = walletLauncher()->getInterface().close(d->handle, true, appid());
d->handle = -1;
d->folder.clear();
d->name.clear();
if (r.isValid()) {
return r;
} else {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return -1;
}
}
const QString &Wallet::walletName() const
{
return d->name;
}
bool Wallet::isOpen() const
{
return d->handle != -1;
}
void Wallet::requestChangePassword(WId w)
{
if (w == 0) {
qCDebug(KWALLET_API_LOG) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
}
if (d->handle == -1) {
return;
}
walletLauncher()->getInterface().changePassword(d->name, (qlonglong)w, appid());
}
void Wallet::slotWalletClosed(int handle)
{
if (d->handle == handle) {
d->handle = -1;
d->folder.clear();
d->name.clear();
Q_EMIT walletClosed();
}
}
QStringList Wallet::folderList()
{
if (d->handle == -1) {
return QStringList();
}
QDBusReply<QStringList> r = walletLauncher()->getInterface().folderList(d->handle, appid());
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return QStringList();
} else {
return r;
}
}
QStringList Wallet::entryList()
{
if (d->handle == -1) {
return QStringList();
}
QDBusReply<QStringList> r = walletLauncher()->getInterface().entryList(d->handle, d->folder, appid());
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return QStringList();
} else {
return r;
}
}
bool Wallet::hasFolder(const QString &f)
{
if (d->handle == -1) {
return false;
}
QDBusReply<bool> r = walletLauncher()->getInterface().hasFolder(d->handle, f, appid());
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
}
bool Wallet::createFolder(const QString &f)
{
if (d->handle == -1) {
return false;
}
if (!hasFolder(f)) {
QDBusReply<bool> r = walletLauncher()->getInterface().createFolder(d->handle, f, appid());
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
}
return true; // folder already exists
}
bool Wallet::setFolder(const QString &f)
{
bool rc = false;
if (d->handle == -1) {
return rc;
}
// Don't do this - the folder could have disappeared?
#if 0
if (f == d->folder) {
return true;
}
#endif
if (hasFolder(f)) {
d->folder = f;
rc = true;
}
return rc;
}
bool Wallet::removeFolder(const QString &f)
{
if (d->handle == -1) {
return false;
}
QDBusReply<bool> r = walletLauncher()->getInterface().removeFolder(d->handle, f, appid());
if (d->folder == f) {
setFolder(QString());
}
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
}
const QString &Wallet::currentFolder() const
{
return d->folder;
}
int Wallet::readEntry(const QString &key, QByteArray &value)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<QByteArray> r = walletLauncher()->getInterface().readEntry(d->handle, d->folder, key, appid());
if (r.isValid()) {
value = r;
rc = 0;
}
return rc;
}
QMap<QString, QByteArray> Wallet::entriesList(bool *ok) const
{
QMap<QString, QByteArray> entries;
registerTypes();
if (d->handle == -1) {
if (ok) {
*ok = false;
}
return entries;
}
QDBusReply<QVariantMap> reply = walletLauncher()->getInterface().entriesList(d->handle, d->folder, appid());
if (reply.isValid()) {
if (ok) {
*ok = true;
}
// convert <QString, QVariant> to <QString, QByteArray>
const QVariantMap val = reply.value();
for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
entries.insert(it.key(), it.value().toByteArray());
}
}
return entries;
}
int Wallet::renameEntry(const QString &oldName, const QString &newName)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
QDBusReply<int> r = walletLauncher()->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
QT_WARNING_POP
if (r.isValid()) {
rc = r;
}
return rc;
}
int Wallet::readMap(const QString &key, QMap<QString, QString> &value)
{
int rc = -1;
registerTypes();
if (d->handle == -1) {
return rc;
}
QDBusReply<QByteArray> r = walletLauncher()->getInterface().readMap(d->handle, d->folder, key, appid());
if (r.isValid()) {
rc = 0;
QByteArray v = r;
if (!v.isEmpty()) {
QDataStream ds(&v, QIODevice::ReadOnly);
ds >> value;
}
}
return rc;
}
QMap<QString, QMap<QString, QString>> Wallet::mapList(bool *ok) const
{
QMap<QString, QMap<QString, QString>> list;
registerTypes();
if (d->handle == -1) {
if (ok) {
*ok = false;
}
return list;
}
QDBusReply<QVariantMap> reply = walletLauncher()->getInterface().mapList(d->handle, d->folder, appid());
if (reply.isValid()) {
if (ok) {
*ok = true;
}
const QVariantMap val = reply.value();
for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
QByteArray mapData = it.value().toByteArray();
if (!mapData.isEmpty()) {
QDataStream ds(&mapData, QIODevice::ReadOnly);
QMap<QString, QString> v;
ds >> v;
list.insert(it.key(), v);
}
}
}
return list;
}
int Wallet::readPassword(const QString &key, QString &value)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<QString> r = walletLauncher()->getInterface().readPassword(d->handle, d->folder, key, appid());
if (r.isValid()) {
value = r;
rc = 0;
}
return rc;
}
QMap<QString, QString> Wallet::passwordList(bool *ok) const
{
QMap<QString, QString> passList;
registerTypes();
if (d->handle == -1) {
if (ok) {
*ok = false;
}
return passList;
}
QDBusReply<QVariantMap> reply = walletLauncher()->getInterface().passwordList(d->handle, d->folder, appid());
if (reply.isValid()) {
if (ok) {
*ok = true;
}
const QVariantMap val = reply.value();
for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
passList.insert(it.key(), it.value().toString());
}
}
return passList;
}
int Wallet::writeEntry(const QString &key, const QByteArray &value, EntryType entryType)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<int> r = walletLauncher()->getInterface().writeEntry(d->handle, d->folder, key, value, int(entryType), appid());
if (r.isValid()) {
rc = r;
}
return rc;
}
int Wallet::writeEntry(const QString &key, const QByteArray &value)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<int> r = walletLauncher()->getInterface().writeEntry(d->handle, d->folder, key, value, appid());
if (r.isValid()) {
rc = r;
}
return rc;
}
int Wallet::writeMap(const QString &key, const QMap<QString, QString> &value)
{
int rc = -1;
registerTypes();
if (d->handle == -1) {
return rc;
}
QByteArray mapData;
QDataStream ds(&mapData, QIODevice::WriteOnly);
ds << value;
QDBusReply<int> r = walletLauncher()->getInterface().writeMap(d->handle, d->folder, key, mapData, appid());
if (r.isValid()) {
rc = r;
}
return rc;
}
int Wallet::writePassword(const QString &key, const QString &value)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<int> r = walletLauncher()->getInterface().writePassword(d->handle, d->folder, key, value, appid());
if (r.isValid()) {
rc = r;
}
return rc;
}
bool Wallet::hasEntry(const QString &key)
{
if (d->handle == -1) {
return false;
}
QDBusReply<bool> r = walletLauncher()->getInterface().hasEntry(d->handle, d->folder, key, appid());
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
}
int Wallet::removeEntry(const QString &key)
{
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<int> r = walletLauncher()->getInterface().removeEntry(d->handle, d->folder, key, appid());
if (r.isValid()) {
rc = r;
}
return rc;
}
Wallet::EntryType Wallet::entryType(const QString &key)
{
int rc = 0;
if (d->handle == -1) {
return Wallet::Unknown;
}
QDBusReply<int> r = walletLauncher()->getInterface().entryType(d->handle, d->folder, key, appid());
if (r.isValid()) {
rc = r;
}
return static_cast<EntryType>(rc);
}
void Wallet::WalletPrivate::walletServiceUnregistered()
{
if (handle >= 0) {
q->slotWalletClosed(handle);
}
}
void Wallet::slotFolderUpdated(const QString &wallet, const QString &folder)
{
if (d->name == wallet) {
Q_EMIT folderUpdated(folder);
}
}
void Wallet::slotFolderListUpdated(const QString &wallet)
{
if (d->name == wallet) {
Q_EMIT folderListUpdated();
}
}
void Wallet::slotApplicationDisconnected(const QString &wallet, const QString &application)
{
if (d->handle >= 0 && d->name == wallet && application == appid()) {
slotWalletClosed(d->handle);
}
}
void Wallet::walletAsyncOpened(int tId, int handle)
{
// ignore responses to calls other than ours
if (d->transactionId != tId || d->handle != -1) {
return;
}
// disconnect the async signal
disconnect(this, SLOT(walletAsyncOpened(int, int)));
d->handle = handle;
Q_EMIT walletOpened(handle > 0);
}
void Wallet::emitWalletAsyncOpenError()
{
Q_EMIT walletOpened(false);
}
void Wallet::emitWalletOpened()
{
Q_EMIT walletOpened(true);
}
bool Wallet::folderDoesNotExist(const QString &wallet, const QString &folder)
{
if (walletLauncher()->m_walletEnabled) {
QDBusReply<bool> r = walletLauncher()->getInterface().folderDoesNotExist(wallet, folder);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
} else {
return false;
}
}
bool Wallet::keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key)
{
if (walletLauncher()->m_walletEnabled) {
QDBusReply<bool> r = walletLauncher()->getInterface().keyDoesNotExist(wallet, folder, key);
if (!r.isValid()) {
qCDebug(KWALLET_API_LOG) << "Invalid DBus reply: " << r.error();
return false;
} else {
return r;
}
} else {
return false;
}
}
void Wallet::virtual_hook(int, void *)
{
// BASE::virtual_hook( id, data );
}
KWalletDLauncher::KWalletDLauncher()
: m_wallet_deamon(nullptr)
, m_cgroup(KSharedConfig::openConfig(QStringLiteral("kwalletrc"), KConfig::NoGlobals)->group(QStringLiteral("Wallet")))
, m_walletEnabled(false)
{
m_walletEnabled = m_cgroup.readEntry("Enabled", true);
if (!m_walletEnabled) {
qCDebug(KWALLET_API_LOG) << "The wallet service was disabled by the user";
return;
}
m_wallet_deamon = new org::kde::KWallet(QString::fromLatin1(s_kwalletdServiceName), QStringLiteral("/modules/kwalletd6"), QDBusConnection::sessionBus());
}
KWalletDLauncher::~KWalletDLauncher()
{
delete m_wallet_deamon;
}
org::kde::KWallet &KWalletDLauncher::getInterface()
{
Q_ASSERT(m_wallet_deamon != nullptr);
// check if kwalletd is already running
QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface();
if (!bus->isServiceRegistered(QString::fromLatin1(s_kwalletdServiceName))) {
// not running! check if it is enabled.
if (m_walletEnabled) {
// wallet is enabled! try launching it
QDBusReply<void> reply = bus->startService(QString::fromLatin1(s_kwalletdServiceName));
if (!reply.isValid()) {
qCritical() << "Couldn't start kwalletd: " << reply.error();
}
if (!bus->isServiceRegistered(QString::fromLatin1(s_kwalletdServiceName))) {
qCDebug(KWALLET_API_LOG) << "The kwalletd service is still not registered";
} else {
qCDebug(KWALLET_API_LOG) << "The kwalletd service has been registered";
}
} else {
qCritical() << "The kwalletd service has been disabled";
}
}
return *m_wallet_deamon;
}
} // namespace KWallet
#include "moc_kwallet.cpp"
@@ -0,0 +1,553 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2002-2004 George Staikos <staikos@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef _KWALLET_H
#define _KWALLET_H
#include <QObject>
#include <QStringList>
#include <qwindowdefs.h> // krazy:exclude=includes (for WId)
#include <kwallet_export.h>
/**
* NOTE: KSecretsService folder semantics
* The KWallet API uses folders for organising items. KSecretsService does not
* have this notion. But it uses attributes that can be applied arbitrarily on
* all the items. The KWallet code that maps to KSecretsService applies an special
* attribute KSS_ATTR_ENTRYFOLDER to all items with the currentFolder() value.
* The KWallet folder API's calls will always succeed and they'll only change the
* current folder value. The folderList() call will scan all the collection
* items and collect the KSS_ATTR_ENTRYFOLDER attributes into a list.
*/
/**
* NOTE: KWalet API distinguish KSecretsService collection items by attaching
* them some specific attributes, defined below
*/
#define KSS_ATTR_ENTRYFOLDER "kwallet.folderName"
#define KSS_ATTR_WALLETTYPE "kwallet.type"
namespace KWallet
{
/**
* KDE Wallet
*
* This class implements a generic system-wide Wallet for KDE. This is the
* ONLY public interface.
*
* @author George Staikos <staikos@kde.org>
* @short KDE Wallet Class
*/
class KWALLET_EXPORT Wallet : public QObject
{
Q_OBJECT
protected:
/**
* Construct a KWallet object.
* @internal
* @param handle The handle for the wallet.
* @param name The name of the wallet.
*/
Wallet(int handle, const QString &name);
/**
* Copy a KWallet object.
* @internal
*/
Wallet(const Wallet &);
public:
enum EntryType {
Unknown = 0,
Password,
Stream,
Map,
Unused = 0xffff,
};
/**
* Destroy a KWallet object. Closes the wallet.
*/
~Wallet() override;
/**
* List all the wallets available.
* @return Returns a list of the names of all wallets that are
* open.
*/
static QStringList walletList();
/**
* Determine if the KDE wallet is enabled. Normally you do
* not need to use this because openWallet() will just fail.
* @return Returns true if the wallet enabled, else false.
*/
static bool isEnabled();
/**
* Determine if the wallet @p name is open by any application.
* @param name The name of the wallet to check.
* @return Returns true if the wallet is open, else false.
*/
static bool isOpen(const QString &name);
/**
* Close the wallet @p name. The wallet will only be closed
* if it is open but not in use (rare), or if it is forced
* closed.
* @param name The name of the wallet to close.
* @param force Set true to force the wallet closed even if it
* is in use by others.
* @return Returns 0 on success, non-zero on error.
*/
static int closeWallet(const QString &name, bool force);
/**
* Delete the wallet @p name. The wallet will be forced closed
* first.
* @param name The name of the wallet to delete.
* @return Returns 0 on success, non-zero on error.
*/
static int deleteWallet(const QString &name);
/**
* Disconnect the application @p app from @p wallet.
* @param wallet The name of the wallet to disconnect.
* @param app The name of the application to disconnect.
* @return Returns true on success, false on error.
*/
static bool disconnectApplication(const QString &wallet, const QString &app);
enum OpenType {
Synchronous = 0,
Asynchronous,
Path,
OpenTypeUnused = 0xff,
};
/**
* Open the wallet @p name. The user will be prompted to
* allow your application to open the wallet, and may be
* prompted for a password. You are responsible for deleting
* this object when you are done with it.
* @param name The name of the wallet to open.
* @param ot If Asynchronous, the call will return
* immediately with a non-null pointer to an
* invalid wallet. You must immediately connect
* the walletOpened() signal to a slot so that
* you will know when it is opened, or when it
* fails.
* @param w The window id to associate any dialogs with. You can pass
* 0 if you don't have a window the password dialog should
* associate with.
* @return Returns a pointer to the wallet if successful,
* or a null pointer on error or if rejected.
* A null pointer can also be returned if user choose to
* deactivate the wallet system.
*/
static Wallet *openWallet(const QString &name, WId w, OpenType ot = Synchronous);
/**
* List the applications that are using the wallet @p wallet.
* @param wallet The wallet to query.
* @return Returns a list of all D-Bus application IDs using
* the wallet.
*/
static QStringList users(const QString &wallet);
/**
* The name of the wallet used to store local passwords.
*/
static const QString LocalWallet();
/**
* The name of the wallet used to store network passwords.
*/
static const QString NetworkWallet();
/**
* The standardized name of the password folder.
* It is automatically created when a wallet is created, but
* the user may still delete it so you should check for its
* existence and recreate it if necessary and desired.
*/
static const QString PasswordFolder();
/**
* The standardized name of the form data folder.
* It is automatically created when a wallet is created, but
* the user may still delete it so you should check for its
* existence and recreate it if necessary and desired.
*/
static const QString FormDataFolder();
/**
* Request to the wallet service to change the password of
* the wallet @p name.
* @param name The wallet to change the password of.
* @param w The window id to associate any dialogs with. You can pass
* 0 if you don't have a window the password dialog should
* associate with.
*/
static void changePassword(const QString &name, WId w);
/**
* This syncs the wallet file on disk with what is in memory.
* You don't normally need to use this. It happens
* automatically on close.
* @return Returns 0 on success, non-zero on error.
*/
virtual int sync();
/**
* This closes and locks the current wallet. It will
* disconnect all applications using the wallet.
* @return Returns 0 on success, non-zero on error.
*/
virtual int lockWallet();
/**
* The name of the current wallet.
*/
virtual const QString &walletName() const;
/**
* Determine if the current wallet is open, and is a valid
* wallet handle.
* @return Returns true if the wallet handle is valid and open.
*/
virtual bool isOpen() const;
/**
* Request to the wallet service to change the password of
* the current wallet.
* @param w The window id to associate any dialogs with. You can pass
* 0 if you don't have a window the password dialog should
* associate with.
*/
virtual void requestChangePassword(WId w);
/**
* Obtain the list of all folders contained in the wallet.
* @return Returns an empty list if the wallet is not open.
*/
virtual QStringList folderList();
/**
* Determine if the folder @p f exists in the wallet.
* @param f the name of the folder to check for
* @return Returns true if the folder exists in the wallet.
*/
virtual bool hasFolder(const QString &f);
/**
* Set the current working folder to @p f. The folder must
* exist, or this call will fail. Create a folder with
* createFolder().
* @param f the name of the folder to make the working folder
* @return Returns true if the folder was successfully set.
*/
virtual bool setFolder(const QString &f);
/**
* Remove the folder @p f and all its entries from the wallet.
* @param f the name of the folder to remove
* @return Returns true if the folder was successfully removed.
*/
virtual bool removeFolder(const QString &f);
/**
* Created the folder @p f.
* @param f the name of the folder to create
* @return Returns true if the folder was successfully created.
*/
virtual bool createFolder(const QString &f);
/**
* Determine the current working folder in the wallet.
* If the folder name is empty, it is working in the global
* folder, which is valid but discouraged.
* @return Returns the current working folder.
*/
virtual const QString &currentFolder() const;
/**
* Return the list of keys of all entries in this folder.
* @return Returns an empty list if the wallet is not open, or
* if the folder is empty.
*/
virtual QStringList entryList();
// TODO KDE5: a entryList(folder) so that kwalletmanager can list a folder without
// having to call setFolder before and after (which calls contains() in each)
/**
* Rename the entry @p oldName to @p newName.
* @param oldName The original key of the entry.
* @param newName The new key of the entry.
* @return Returns 0 on success, non-zero on error.
*/
virtual int renameEntry(const QString &oldName, const QString &newName);
/**
* Read the entry @p key from the current folder.
* The entry format is unknown except that it is either a
* QByteArray or a QDataStream, which effectively means that
* it is anything.
* @param key The key of the entry to read.
* @param value A buffer to fill with the value.
* @return Returns 0 on success, non-zero on error.
*/
virtual int readEntry(const QString &key, QByteArray &value);
/**
* Read the map entry @p key from the current folder.
* @param key The key of the entry to read.
* @param value A map buffer to fill with the value.
* @return Returns 0 on success, non-zero on error. Will
* return an error if the key was not originally
* written as a map.
*/
virtual int readMap(const QString &key, QMap<QString, QString> &value);
/**
* Read the password entry @p key from the current folder.
* @param key The key of the entry to read.
* @param value A password buffer to fill with the value.
* @return Returns 0 on success, non-zero on error. Will
* return an error if the key was not originally
* written as a password.
*/
virtual int readPassword(const QString &key, QString &value);
/**
* Get a list of all the entries in the current folder. The entry
* format is unknown except that it is either a QByteArray or a
* QDataStream, which effectively means that it could be anything.
*
* @param ok if not nullptr, the object this parameter points to will be set
* to true to indicate success or false otherwise
* @return a map of key/value pairs where the key in the map is the entry key
*
* @since 5.72
*/
QMap<QString, QByteArray> entriesList(bool *ok) const;
/**
* Get a list of all the maps in the current folder.
*
* @param ok if not nullptr, the object this parameter points to will be set
* to true to indicate success or false otherwise. Note that if any
* of the keys was not originally written as a map, the object will
* be set to false
*
* @return a map of key/value pairs where the key in the map is the entry key
*
* @since 5.72
*/
QMap<QString, QMap<QString, QString>> mapList(bool *ok) const;
/**
* Get a list of all the passwords in the current folder, which can
* be used to populate a list view in a password manager.
*
* @param ok if not nullptr, the object this parameter points to will be
* set to true to indicate success or false otherwise. Note that
* the object will be set to false if any of the keys was not
* originally written as a password
*
* @return a map of key/value pairs, where the key in the map is the entry key
*
* @since 5.72
*/
QMap<QString, QString> passwordList(bool *ok) const;
/**
* Write @p key = @p value as a binary entry to the current
* folder. Be careful with this, it could cause inconsistency
* in the future since you can put an arbitrary entry type in
* place.
* @param key The key of the new entry.
* @param value The value of the entry.
* @param entryType The type of the entry.
* @return Returns 0 on success, non-zero on error.
*/
virtual int writeEntry(const QString &key, const QByteArray &value, EntryType entryType);
/**
* Write @p key = @p value as a binary entry to the current
* folder.
* @param key The key of the new entry.
* @param value The value of the entry.
* @return Returns 0 on success, non-zero on error.
*/
virtual int writeEntry(const QString &key, const QByteArray &value);
/**
* Write @p key = @p value as a map to the current folder.
* @param key The key of the new entry.
* @param value The value of the map.
* @return Returns 0 on success, non-zero on error.
*/
virtual int writeMap(const QString &key, const QMap<QString, QString> &value);
/**
* Write @p key = @p value as a password to the current folder.
* @param key The key of the new entry.
* @param value The value of the password.
* @return Returns 0 on success, non-zero on error.
*/
virtual int writePassword(const QString &key, const QString &value);
/**
* Determine if the current folder has they entry @p key.
* @param key The key to search for.
* @return Returns true if the folder contains @p key.
*/
virtual bool hasEntry(const QString &key);
/**
* Remove the entry @p key from the current folder.
* @param key The key to remove.
* @return Returns 0 on success, non-zero on error.
*/
virtual int removeEntry(const QString &key);
/**
* Determine the type of the entry @p key in this folder.
* @param key The key to look up.
* @return Returns an enumerated type representing the type
* of the entry.
*/
virtual EntryType entryType(const QString &key);
/**
* Determine if a folder does not exist in a wallet. This
* does not require decryption of the wallet.
* This is a handy optimization to avoid prompting the user
* if your data is certainly not in the wallet.
* @param wallet The wallet to look in.
* @param folder The folder to look up.
* @return Returns true if the folder does NOT exist in the
* wallet, or the wallet does not exist.
*/
static bool folderDoesNotExist(const QString &wallet, const QString &folder);
/**
* Determine if an entry in a folder does not exist in a
* wallet. This does not require decryption of the wallet.
* This is a handy optimization to avoid prompting the user
* if your data is certainly not in the wallet.
* @param wallet The wallet to look in.
* @param folder The folder to look in.
* @param key The key to look up.
* @return Returns true if the key does NOT exist in the
* wallet, or the folder or wallet does not exist.
*/
static bool keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key);
Q_SIGNALS:
/**
* Emitted when this wallet is closed.
*/
void walletClosed();
/**
* Emitted when a folder in this wallet is updated.
* @param folder The folder that was updated.
*/
void folderUpdated(const QString &folder);
/**
* Emitted when the folder list is changed in this wallet.
*/
void folderListUpdated();
/**
* Emitted when a folder in this wallet is removed.
* @param folder The folder that was removed.
*/
void folderRemoved(const QString &folder);
/**
* Emitted when a wallet is opened in asynchronous mode.
* @param success True if the wallet was opened successfully.
*/
void walletOpened(bool success);
private Q_SLOTS:
/**
* @internal
* D-Bus slot for signals emitted by the wallet service.
*/
KWALLET_NO_EXPORT void slotWalletClosed(int handle);
/**
* @internal
* D-Bus slot for signals emitted by the wallet service.
*/
KWALLET_NO_EXPORT void slotFolderUpdated(const QString &wallet, const QString &folder);
/**
* @internal
* D-Bus slot for signals emitted by the wallet service.
*/
KWALLET_NO_EXPORT void slotFolderListUpdated(const QString &wallet);
/**
* @internal
* D-Bus slot for signals emitted by the wallet service.
*/
KWALLET_NO_EXPORT void slotApplicationDisconnected(const QString &wallet, const QString &application);
/**
* @internal
* Callback for kwalletd
* @param tId identifier for the open transaction
* @param handle the wallet's handle
*/
KWALLET_NO_EXPORT void walletAsyncOpened(int tId, int handle);
/**
* @internal
* D-Bus error slot.
*/
KWALLET_NO_EXPORT void emitWalletAsyncOpenError();
/**
* @internal
* Emits wallet opening success.
*/
KWALLET_NO_EXPORT void emitWalletOpened();
/**
* @internal
* Receives status changed notifications from KSecretsService infrastructure
*/
KWALLET_NO_EXPORT void slotCollectionStatusChanged(int);
/**
* @internal
* Received delete notification from KSecretsService infrastructure
*/
KWALLET_NO_EXPORT void slotCollectionDeleted();
private:
class WalletPrivate;
WalletPrivate *const d;
Q_PRIVATE_SLOT(d, void walletServiceUnregistered())
protected:
/**
* @internal
*/
virtual void virtual_hook(int id, void *data);
};
}
#endif //_KWALLET_H
@@ -0,0 +1,738 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2002-2004 George Staikos <staikos@kde.org>
SPDX-FileCopyrightText: 2008 Michael Leupold <lemma@confuego.org>
SPDX-FileCopyrightText: 2010 Frank Osterfeld <osterfeld@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kwallet.h"
#include <KConfigGroup>
#include <KSharedConfig>
#include <QApplication>
#include <QDebug>
#include <QPointer>
#include <QWidget>
#include <Carbon/Carbon.h>
#include <Security/SecKeychain.h>
#include <Security/Security.h>
// TODO: OSX_KEYCHAIN_PORT_DISABLED is never defined, all the enclosing code should be removed
using namespace KWallet;
typedef QMap<QString, QString> StringStringMap;
Q_DECLARE_METATYPE(StringStringMap)
typedef QMap<QString, StringStringMap> StringToStringStringMapMap;
Q_DECLARE_METATYPE(StringToStringStringMapMap)
typedef QMap<QString, QByteArray> StringByteArrayMap;
Q_DECLARE_METATYPE(StringByteArrayMap)
namespace
{
template<typename T>
struct CFReleaser {
explicit CFReleaser(const T &r)
: ref(r)
{
}
~CFReleaser()
{
CFRelease(ref);
}
T ref;
};
}
static QString asQString(CFStringRef sr)
{
return QString::fromLatin1(CFStringGetCStringPtr(sr, NULL)); // TODO Latin1 correct?
}
static QString errorString(OSStatus s)
{
const CFReleaser<CFStringRef> ref(SecCopyErrorMessageString(s, NULL));
return asQString(ref.ref);
}
static bool isError(OSStatus s, QString *errMsg)
{
if (errMsg) {
*errMsg = errorString(s);
}
return s != 0;
}
static QString appid()
{
return qApp->applicationName();
}
static OSStatus removeEntryImplementation(const QString &walletName, const QString &key)
{
const QByteArray serviceName(walletName.toUtf8());
const QByteArray accountName(key.toUtf8());
SecKeychainItemRef itemRef;
QString errMsg;
OSStatus result =
SecKeychainFindGenericPassword(NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, &itemRef);
if (isError(result, &errMsg)) {
qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
return result;
}
const CFReleaser<SecKeychainItemRef> itemReleaser(itemRef);
result = SecKeychainItemDelete(itemRef);
if (isError(result, &errMsg)) {
qWarning() << "Could not delete password:" << qPrintable(errMsg);
return result;
}
return result;
}
const QString Wallet::LocalWallet()
{
KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group("Wallet"));
if (!cfg.readEntry("Use One Wallet", true)) {
QString tmp = cfg.readEntry("Local Wallet", "localwallet");
if (tmp.isEmpty()) {
return QStringLiteral("localwallet");
}
return tmp;
}
QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
if (tmp.isEmpty()) {
return QStringLiteral("kdewallet");
}
return tmp;
}
const QString Wallet::NetworkWallet()
{
KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group("Wallet"));
QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
if (tmp.isEmpty()) {
return QStringLiteral("kdewallet");
}
return tmp;
}
const QString Wallet::PasswordFolder()
{
return QStringLiteral("Passwords");
}
const QString Wallet::FormDataFolder()
{
return QStringLiteral("Form Data");
}
class Q_DECL_HIDDEN Wallet::WalletPrivate
{
public:
WalletPrivate(Wallet *wallet, int h, const QString &n)
: q(wallet)
, name(n)
, handle(h)
{
}
void walletServiceUnregistered();
Wallet *q;
QString name;
QString folder;
int handle;
int transactionId;
};
void Wallet::WalletPrivate::walletServiceUnregistered()
{
if (handle >= 0) {
q->slotWalletClosed(handle);
}
}
Wallet::Wallet(int handle, const QString &name)
: QObject(0L)
, d(new WalletPrivate(this, handle, name))
{
Q_UNUSED(handle);
}
Wallet::~Wallet()
{
delete d;
}
QStringList Wallet::walletList()
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().wallets();
#else
return QStringList();
#endif
}
void Wallet::changePassword(const QString &name, WId w)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (w == 0) {
qDebug() << "Pass a valid window to KWallet::Wallet::changePassword().";
}
walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
#endif
}
bool Wallet::isEnabled()
{
// PENDING(frank) check
return true;
}
bool Wallet::isOpen(const QString &name)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().isOpen(name); // default is false
#else
return true;
#endif
}
int Wallet::closeWallet(const QString &name, bool force)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
return r.isValid() ? r : -1;
#else
return 0;
#endif
}
int Wallet::deleteWallet(const QString &name)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
return r.isValid() ? r : -1;
#else
return -1;
#endif
}
Wallet *Wallet::openWallet(const QString &name, WId w, OpenType ot)
{
Q_UNUSED(w);
Q_UNUSED(ot);
Wallet *wallet = new Wallet(-1, name);
QMetaObject::invokeMethod(wallet, "emitWalletOpened", Qt::QueuedConnection);
return wallet;
}
bool Wallet::disconnectApplication(const QString &wallet, const QString &app)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
#else
return true;
#endif
}
QStringList Wallet::users(const QString &name)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().users(name); // default is QStringList()
#else
return QStringList();
#endif
}
int Wallet::sync()
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return -1;
}
walletLauncher->getInterface().sync(d->handle, appid());
#endif
return 0;
}
int Wallet::lockWallet()
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return -1;
}
QDBusReply<int> r = walletLauncher->getInterface().close(d->handle, true, appid());
d->handle = -1;
d->folder.clear();
d->name.clear();
if (r.isValid()) {
return r;
}
#endif
return -1;
}
const QString &Wallet::walletName() const
{
return d->name;
}
bool Wallet::isOpen() const
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return d->handle != -1;
#else
return true;
#endif
}
void Wallet::requestChangePassword(WId w)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (w == 0) {
qDebug() << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
}
if (d->handle == -1) {
return;
}
walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
#endif
}
void Wallet::slotWalletClosed(int handle)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == handle) {
d->handle = -1;
d->folder.clear();
d->name.clear();
Q_EMIT walletClosed();
}
#endif
}
QStringList Wallet::folderList()
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return QStringList();
}
QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
return r;
#else
return QStringList();
#endif
}
QStringList Wallet::entryList()
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return QStringList();
}
QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
return r;
#else
return QStringList();
#endif
}
bool Wallet::hasFolder(const QString &f)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return false;
}
QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
return r; // default is false
#else
return true;
#endif
}
bool Wallet::createFolder(const QString &f)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return false;
}
if (!hasFolder(f)) {
QDBusReply<bool> r = walletLauncher->getInterface().createFolder(d->handle, f, appid());
return r;
}
return true; // folder already exists
#else
return true;
#endif
}
bool Wallet::setFolder(const QString &f)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
bool rc = false;
if (d->handle == -1) {
return rc;
}
// Don't do this - the folder could have disappeared?
#if 0
if (f == d->folder) {
return true;
}
#endif
if (hasFolder(f)) {
d->folder = f;
rc = true;
}
return rc;
#else
return true;
#endif
}
bool Wallet::removeFolder(const QString &f)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle == -1) {
return false;
}
QDBusReply<bool> r = walletLauncher->getInterface().removeFolder(d->handle, f, appid());
if (d->folder == f) {
setFolder(QString());
}
return r; // default is false
#else
return true;
#endif
}
const QString &Wallet::currentFolder() const
{
return d->folder;
}
int Wallet::readEntry(const QString &key, QByteArray &value)
{
const QByteArray serviceName(walletName().toUtf8());
const QByteArray accountName(key.toUtf8());
UInt32 passwordSize = 0;
void *passwordData = 0;
QString errMsg;
if (isError(SecKeychainFindGenericPassword(NULL,
serviceName.size(),
serviceName.constData(),
accountName.size(),
accountName.constData(),
&passwordSize,
&passwordData,
NULL),
&errMsg)) {
qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
return -1;
}
value = QByteArray(reinterpret_cast<const char *>(passwordData), passwordSize);
SecKeychainItemFreeContent(NULL, passwordData);
return 0;
}
int Wallet::readEntryList(const QString &key, QMap<QString, QByteArray> &value)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
registerTypes();
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<QVariantMap> r = walletLauncher->getInterface().readEntryList(d->handle, d->folder, key, appid());
if (r.isValid()) {
rc = 0;
// convert <QString, QVariant> to <QString, QByteArray>
const QVariantMap val = r.value();
for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
value.insert(it.key(), it.value().toByteArray());
}
}
return rc;
#else
return -1;
#endif
}
int Wallet::renameEntry(const QString &oldName, const QString &newName)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<int> r = walletLauncher->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
if (r.isValid()) {
rc = r;
}
return rc;
#else
return -1;
#endif
}
int Wallet::readMap(const QString &key, QMap<QString, QString> &value)
{
QByteArray v;
const int ret = readEntry(key, v);
if (ret != 0) {
return ret;
}
if (!v.isEmpty()) {
QDataStream ds(&v, QIODevice::ReadOnly);
ds >> value;
}
return 0;
}
int Wallet::readMapList(const QString &key, QMap<QString, QMap<QString, QString>> &value)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
registerTypes();
int rc = -1;
if (d->handle == -1) {
return rc;
}
QDBusReply<QVariantMap> r = walletLauncher->getInterface().readMapList(d->handle, d->folder, key, appid());
if (r.isValid()) {
rc = 0;
const QVariantMap val = r.value();
for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
QByteArray mapData = it.value().toByteArray();
if (!mapData.isEmpty()) {
QDataStream ds(&mapData, QIODevice::ReadOnly);
QMap<QString, QString> v;
ds >> v;
value.insert(it.key(), v);
}
}
}
return rc;
#else
return -1;
#endif
}
int Wallet::readPassword(const QString &key, QString &value)
{
QByteArray ba;
const int ret = readEntry(key, ba);
if (ret == 0) {
value = QString::fromUtf8(ba.constData());
}
return ret;
}
int Wallet::readPasswordList(const QString &key, QMap<QString, QString> &value)
{
return -1;
}
static OSStatus writeEntryImplementation(const QString &walletName, const QString &key, const QByteArray &value)
{
const QByteArray serviceName(walletName.toUtf8());
const QByteArray accountName(key.toUtf8());
QString errMsg;
OSStatus err = SecKeychainAddGenericPassword(NULL,
serviceName.size(),
serviceName.constData(),
accountName.size(),
accountName.constData(),
value.size(),
value.constData(),
NULL);
if (err == errSecDuplicateItem) {
err = removeEntryImplementation(walletName, key);
if (isError(err, &errMsg)) {
qWarning() << "Could not delete old key in keychain for replacing: " << qPrintable(errMsg);
return err;
}
}
if (isError(err, &errMsg)) {
qWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
return err;
}
// qDebug() << "Successfully written out key:" << key;
return err;
}
int Wallet::writeEntry(const QString &key, const QByteArray &password, EntryType entryType)
{
Q_UNUSED(entryType)
return writeEntryImplementation(walletName(), key, password);
}
int Wallet::writeEntry(const QString &key, const QByteArray &value)
{
return writeEntryImplementation(walletName(), key, value);
}
int Wallet::writeMap(const QString &key, const QMap<QString, QString> &value)
{
QByteArray mapData;
QDataStream ds(&mapData, QIODevice::WriteOnly);
ds << value;
return writeEntry(key, mapData);
}
int Wallet::writePassword(const QString &key, const QString &value)
{
return writeEntry(key, value.toUtf8());
}
bool Wallet::hasEntry(const QString &key)
{
const QByteArray serviceName(walletName().toUtf8());
const QByteArray accountName(key.toUtf8());
return !isError(
SecKeychainFindGenericPassword(NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, NULL),
0);
}
int Wallet::removeEntry(const QString &key)
{
return removeEntryImplementation(walletName(), key);
}
Wallet::EntryType Wallet::entryType(const QString &key)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
int rc = 0;
if (d->handle == -1) {
return Wallet::Unknown;
}
QDBusReply<int> r = walletLauncher->getInterface().entryType(d->handle, d->folder, key, appid());
if (r.isValid()) {
rc = r;
}
return static_cast<EntryType>(rc);
#else
return Wallet::Unknown;
#endif
}
void Wallet::slotFolderUpdated(const QString &wallet, const QString &folder)
{
if (d->name == wallet) {
Q_EMIT folderUpdated(folder);
}
}
void Wallet::slotFolderListUpdated(const QString &wallet)
{
if (d->name == wallet) {
Q_EMIT folderListUpdated();
}
}
void Wallet::slotApplicationDisconnected(const QString &wallet, const QString &application)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
if (d->handle >= 0 && d->name == wallet && application == appid()) {
slotWalletClosed(d->handle);
}
#endif
}
void Wallet::walletAsyncOpened(int tId, int handle)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
// ignore responses to calls other than ours
if (d->transactionId != tId || d->handle != -1) {
return;
}
// disconnect the async signal
disconnect(this, SLOT(walletAsyncOpened(int, int)));
d->handle = handle;
Q_EMIT walletOpened(handle > 0);
#endif
}
void Wallet::emitWalletAsyncOpenError()
{
Q_EMIT walletOpened(false);
}
void Wallet::emitWalletOpened()
{
Q_EMIT walletOpened(true);
}
bool Wallet::folderDoesNotExist(const QString &wallet, const QString &folder)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
return r;
#else
return false;
#endif
}
bool Wallet::keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
return r;
#else
return false;
#endif
}
void Wallet::slotCollectionStatusChanged(int status)
{
}
void Wallet::slotCollectionDeleted()
{
d->folder.clear();
d->name.clear();
Q_EMIT walletClosed();
}
void Wallet::virtual_hook(int, void *)
{
// BASE::virtual_hook( id, data );
}
#include "moc_kwallet.cpp"
@@ -0,0 +1,46 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedesktop/Secrets">
<interface name="org.freedesktop.Secret.Collection">
<property name="Items" type="ao" access="read"/>
<property name="Label" type="s" access="readwrite"/>
<property name="Locked" type="b" access="read"/>
<property name="Created" type="t" access="read"/>
<property name="Modified" type="t" access="read"/>
<method name="Delete">
<arg name="prompt" type="o" direction="out"/>
</method>
<method name="SearchItems">
<arg name="attributes" type="a{ss}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="StrStrMap"/>
<arg name="results" type="ao" direction="out"/>
</method>
<method name="CreateItem">
<arg name="properties" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="PropertiesMap"/>
<arg name="secret" type="(oayays)" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="FreedesktopSecret"/>
<arg name="replace" type="b" direction="in"/>
<arg name="item" type="o" direction="out"/>
<arg name="prompt" type="o" direction="out"/>
</method>
<signal name="ItemCreated">
<arg name="item" type="o"/>
</signal>
<signal name="ItemDeleted">
<arg name="item" type="o"/>
</signal>
<signal name="ItemChanged">
<arg name="item" type="o"/>
</signal>
</interface>
</node>
@@ -0,0 +1,37 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedesktop/Secrets">
<interface name="org.freedesktop.Secret.Item">
<property name="Locked" type="b" access="read"/>
<property name="Attributes" type="a{ss}" access="readwrite">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="StrStrMap"/>
</property>
<property name="Label" type="s" access="readwrite"/>
<property name="Type" type="s" access="readwrite"/>
<property name="Created" type="t" access="read"/>
<property name="Modified" type="t" access="read"/>
<method name="Delete">
<arg name="Prompt" type="o" direction="out"/>
</method>
<method name="GetSecret">
<arg name="session" type="o" direction="in"/>
<arg name="secret" type="(oayays)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="FreedesktopSecret"/>
</method>
<method name="SetSecret">
<arg name="secret" type="(oayays)" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="FreedesktopSecret"/>
</method>
</interface>
</node>
@@ -0,0 +1,20 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedesktop/Secrets">
<interface name="org.freedesktop.Secret.Prompt">
<method name="Prompt">
<arg name="window_id" type="s" direction="in"/>
</method>
<method name="Dismiss">
</method>
<!-- Emitted manually -->
<signal name="Completed">
<arg name="dismissed" type="b"/>
<arg name="result" type="v"/>
</signal>
</interface>
</node>
@@ -0,0 +1,72 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedesktop/Secrets">
<interface name="org.freedesktop.Secret.Service">
<property name="Collections" type="ao" access="read" />
<method name="OpenSession">
<arg name="algorithm" type="s" direction="in"/>
<arg name="input" type="v" direction="in"/>
<arg name="output" type="v" direction="out"/>
<arg name="result" type="o" direction="out"/>
</method>
<method name="CreateCollection">
<arg name="properties" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
<arg name="alias" type="s" direction="in"/>
<arg name="collection" type="o" direction="out"/>
<arg name="prompt" type="o" direction="out"/>
</method>
<method name="SearchItems">
<arg name="attributes" type="a{ss}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="StrStrMap"/>
<arg name="unlocked" type="ao" direction="out"/>
<arg name="locked" type="ao" direction="out"/>
</method>
<method name="Unlock">
<arg name="objects" type="ao" direction="in"/>
<arg name="unlocked" type="ao" direction="out"/>
<arg name="prompt" type="o" direction="out"/>
</method>
<method name="Lock">
<arg name="objects" type="ao" direction="in"/>
<arg name="locked" type="ao" direction="out"/>
<arg name="Prompt" type="o" direction="out"/>
</method>
<method name="GetSecrets">
<arg name="items" type="ao" direction="in"/>
<arg name="session" type="o" direction="in"/>
<arg name="secrets" type="a{o(oayays)}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="FreedesktopSecretMap"/>
</method>
<method name="ReadAlias">
<arg name="name" type='s' direction='in'/>
<arg name="collection" type='o' direction='out'/>
</method>
<method name="SetAlias">
<arg name="name" type='s' direction='in'/>
<arg name="collection" type='o' direction='in'/>
</method>
<signal name="CollectionCreated">
<arg name="collection" type="o"/>
</signal>
<signal name="CollectionDeleted">
<arg name="collection" type="o"/>
</signal>
<signal name="CollectionChanged">
<arg name="collection" type="o"/>
</signal>
</interface>
</node>
@@ -0,0 +1,12 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedesktop/Secrets">
<interface name="org.freedesktop.Secret.Session">
<method name="Close">
</method>
</interface>
</node>
@@ -0,0 +1,66 @@
<?xml version="1.0"?>
<!--
Copyright (C) 2019 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
Author: Daiki Ueno <dueno@redhat.com>
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.freedesktop.impl.portal.Secret:
@short_description: Secret portal backend interface
The Secret portal allows sandboxed applications to retrieve a
per-application master secret.
-->
<interface name="org.freedesktop.impl.portal.Secret">
<!--
RetrieveSecret:
@handle: Object path for the #org.freedesktop.impl.portal.Request object representing this call
@app_id: App id of the application
@fd: Writable file descriptor for transporting the secret
@options: Vardict with optional further information
@response: Numeric response
@results: Vardict with the results of the call
Retrieves a master secret for a sandboxed application.
Supported keys in the @options vardict include:
<variablelist>
<varlistentry>
<term>token s</term>
<listitem><para>
An opaque string associated with the retrieve secret.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="RetrieveSecret">
<annotation name="org.gtk.GDBus.C.Name" value="retrieve_secret"/>
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
<arg type="o" name="handle" direction="in"/>
<arg type="s" name="app_id" direction="in"/>
<arg type="h" name="fd" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QVariantMap"/>
<arg type="a{sv}" name="options" direction="in"/>
<arg type="u" name="response" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
<arg type="a{sv}" name="results" direction="out"/>
</method>
<property name="version" type="u" access="read"/>
</interface>
</node>
@@ -0,0 +1,273 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.KWallet">
<signal name="walletListDirty">
</signal>
<signal name="walletCreated">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletOpened">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletAsyncOpened">
<arg name="tId" type="i" direction="out"/>
<arg name="handle" type="i" direction="out"/>
</signal>
<signal name="walletDeleted">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletClosed">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletClosedId">
<arg name="handle" type="i" direction="out"/>
</signal>
<signal name="allWalletsClosed">
</signal>
<signal name="folderListUpdated">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="folderUpdated">
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
</signal>
<signal name="applicationDisconnected">
<arg name="wallet" type="s" direction="out"/>
<arg name="application" type="s" direction="out"/>
</signal>
<method name="isEnabled">
<arg type="b" direction="out"/>
</method>
<method name="open">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="openPath">
<arg type="i" direction="out"/>
<arg name="path" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="openAsync">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<arg name="handleSession" type="b" direction="in"/>
</method>
<method name="openPathAsync">
<arg type="i" direction="out"/>
<arg name="path" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<arg name="handleSession" type="b" direction="in"/>
</method>
<method name="close">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="force" type="b" direction="in"/>
</method>
<method name="close">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="force" type="b" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="sync">
<arg name="handle" type="i" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="deleteWallet">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
</method>
<method name="isOpen">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
</method>
<method name="isOpen">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
</method>
<method name="users">
<arg type="as" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
</method>
<method name="changePassword">
<arg name="wallet" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="wallets">
<arg type="as" direction="out"/>
</method>
<method name="folderList">
<arg type="as" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="hasFolder">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="createFolder">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="removeFolder">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="entryList">
<arg type="as" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readEntry">
<arg type="ay" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readMap">
<arg type="ay" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readPassword">
<arg type="s" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="entriesList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="mapList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="passwordList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="renameEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="oldName" type="s" direction="in"/>
<arg name="newName" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writeEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="ay" direction="in"/>
<arg name="entryType" type="i" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writeEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="ay" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writeMap">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="ay" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writePassword">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="hasEntry">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="entryType">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="removeEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="disconnectApplication">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="application" type="s" direction="in"/>
</method>
<method name="reconfigure">
</method>
<method name="folderDoesNotExist">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="folder" type="s" direction="in"/>
</method>
<method name="keyDoesNotExist">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
</method>
<method name="closeAllWallets">
</method>
<method name="networkWallet">
<arg type="s" direction="out"/>
</method>
<method name="localWallet">
<arg type="s" direction="out"/>
</method>
<method name="pamOpen">
<arg name="wallet" type="s" direction="in"/>
<arg name="passwordHash" type="ay" direction="in"/>
<arg name="sessionTimeout" type="i" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>
@@ -0,0 +1,305 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.KWallet">
<signal name="walletListDirty">
</signal>
<signal name="walletCreated">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletOpened">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletAsyncOpened">
<arg name="tId" type="i" direction="out"/>
<arg name="handle" type="i" direction="out"/>
</signal>
<signal name="walletDeleted">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="walletClosed">
<arg name="wallet" type="s" direction="out"/>
</signal>
<!-- Deprecated, use walletClosedId -->
<signal name="walletClosed">
<arg name="handle" type="i" direction="out"/>
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
</signal>
<signal name="walletClosedId">
<arg name="handle" type="i" direction="out"/>
</signal>
<signal name="allWalletsClosed">
</signal>
<signal name="folderListUpdated">
<arg name="wallet" type="s" direction="out"/>
</signal>
<signal name="folderUpdated">
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
</signal>
<signal name="applicationDisconnected">
<arg name="wallet" type="s" direction="out"/>
<arg name="application" type="s" direction="out"/>
</signal>
<method name="isEnabled">
<arg type="b" direction="out"/>
</method>
<method name="open">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="openPath">
<arg type="i" direction="out"/>
<arg name="path" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="openAsync">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<arg name="handleSession" type="b" direction="in"/>
</method>
<method name="openPathAsync">
<arg type="i" direction="out"/>
<arg name="path" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<arg name="handleSession" type="b" direction="in"/>
</method>
<method name="close">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="force" type="b" direction="in"/>
</method>
<method name="close">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="force" type="b" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="sync">
<arg name="handle" type="i" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="deleteWallet">
<arg type="i" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
</method>
<method name="isOpen">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
</method>
<method name="isOpen">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
</method>
<method name="users">
<arg type="as" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
</method>
<method name="changePassword">
<arg name="wallet" type="s" direction="in"/>
<arg name="wId" type="x" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="wallets">
<arg type="as" direction="out"/>
</method>
<method name="folderList">
<arg type="as" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="hasFolder">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="createFolder">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="removeFolder">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="entryList">
<arg type="as" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readEntry">
<arg type="ay" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readMap">
<arg type="ay" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readPassword">
<arg type="s" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readEntryList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
</method>
<method name="entriesList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readMapList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
</method>
<method name="mapList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="readPasswordList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
</method>
<method name="passwordList">
<arg type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="renameEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="oldName" type="s" direction="in"/>
<arg name="newName" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writeEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="ay" direction="in"/>
<arg name="entryType" type="i" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writeEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="ay" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writeMap">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="ay" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="writePassword">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="value" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="hasEntry">
<arg type="b" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="entryType">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="removeEntry">
<arg type="i" direction="out"/>
<arg name="handle" type="i" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
<arg name="appid" type="s" direction="in"/>
</method>
<method name="disconnectApplication">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="application" type="s" direction="in"/>
</method>
<method name="reconfigure">
</method>
<method name="folderDoesNotExist">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="folder" type="s" direction="in"/>
</method>
<method name="keyDoesNotExist">
<arg type="b" direction="out"/>
<arg name="wallet" type="s" direction="in"/>
<arg name="folder" type="s" direction="in"/>
<arg name="key" type="s" direction="in"/>
</method>
<method name="closeAllWallets">
</method>
<method name="networkWallet">
<arg type="s" direction="out"/>
</method>
<method name="localWallet">
<arg type="s" direction="out"/>
</method>
<method name="pamOpen">
<arg name="wallet" type="s" direction="in"/>
<arg name="passwordHash" type="ay" direction="in"/>
<arg name="sessionTimeout" type="i" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>