[vlc-devel] [RFC PATCH 5/8] keystore: add kwallet module
Thomas Guillem
thomas at gllm.fr
Wed Dec 30 19:37:02 CET 2015
TODO: see #if 0: QDBusServiceWatcher and openWallet(Asynchronous) are not
working. Indeed, signals are not received even when a QApplication is running
(via the qt interface).
---
configure.ac | 33 +++
modules/keystore/Makefile.am | 20 ++
modules/keystore/kwallet.cpp | 566 +++++++++++++++++++++++++++++++++++++++++++
modules/keystore/kwallet.hpp | 69 ++++++
4 files changed, 688 insertions(+)
create mode 100644 modules/keystore/kwallet.cpp
create mode 100644 modules/keystore/kwallet.hpp
diff --git a/configure.ac b/configure.ac
index 9582139..1443e87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4075,6 +4075,39 @@ dnl
PKG_ENABLE_MODULES_VLC([SECRET], [], [libsecret-1], [use libsecret for keystore], [auto])
dnl
+dnl kwallet
+dnl
+AC_ARG_ENABLE(kwallet,
+ [AS_HELP_STRING([--enable-kwallet],
+ [use KWallet for keystore (default auto)])])
+have_kwallet="no"
+KWALLET_CXXFLAGS=""
+KWALLET_LIBS=""
+AS_IF([test "${enable_qt}" != "no" -a "${KDE4_CONFIG}" != "no" -a "${enable_kwallet}" != "no" ], [
+ VLC_SAVE_FLAGS
+ AC_LANG_PUSH([C++])
+ KWALLET_CXXFLAGS="$QT_CFLAGS $CXXFLAGS_qt4 -I`$KDE4_CONFIG --path include`"
+ CPPFLAGS="$CPPFLAGS $KWALLET_CXXFLAGS"
+ AC_CHECK_HEADER([kwallet.h], [
+ KWALLET_LIBS="$QT_LIBS -L`$KDE4_CONFIG --install lib` -lkdeui"
+ LDFLAGS="$LDFLAGS $KWALLET_LIBS"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <kwallet.h>], [
+KWallet::Wallet::LocalWallet();
+ ])], [
+ have_kwallet="yes"
+ ])
+ AC_LANG_POP([C++])
+ VLC_RESTORE_FLAGS
+ ])
+#])
+AS_IF([test "$enable_kwallet" = "yes" -a "$have_kwallet" = "no" ], [
+ AC_MSG_ERROR([KWallet headers or so not found])
+])
+AC_SUBST(KWALLET_CXXFLAGS)
+AC_SUBST(KWALLET_LIBS)
+AM_CONDITIONAL([HAVE_KWALLET], [test "${have_kwallet}" = "yes"])
+
+dnl
dnl Developers helper modules (should be hidden from configure help)
dnl
AC_ARG_ENABLE(devtools, [], [], [enable_devtools="no"])
diff --git a/modules/keystore/Makefile.am b/modules/keystore/Makefile.am
index dc8c526..64787de 100644
--- a/modules/keystore/Makefile.am
+++ b/modules/keystore/Makefile.am
@@ -8,6 +8,26 @@ libsecret_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(SECRET_CFLAGS)
libsecret_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(keystoredir)'
libsecret_plugin_la_LIBADD = $(SECRET_LIBS)
+
+# Meta-object compilation
+
+SUFFIXES += .hpp .moc.cpp
+moc_verbose = $(moc_verbose_$(V))
+moc_verbose_ = $(moc_verbose__$(AM_DEFAULT_VERBOSITY))
+moc_verbose_0 = @echo " MOC " $@;
+moc_verbose__0 = $(moc_verbose_0)
+
+.hpp.moc.cpp:
+ $(moc_verbose)$(MOC) $(MOC_CPPFLAGS) -o $@ $<
+
+libkwallet_plugin_la_SOURCES = keystore/kwallet.cpp keystore/kwallet.moc.cpp
+libkwallet_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
+libkwallet_plugin_la_CXXFLAGS = $(KWALLET_CXXFLAGS)
+libkwallet_plugin_la_LIBADD = $(KWALLET_LIBS)
+if HAVE_KWALLET
+keystore_LTLIBRARIES += libkwallet_plugin.la
+endif
+
keystore_LTLIBRARIES += \
$(LTLIBsecret)
diff --git a/modules/keystore/kwallet.cpp b/modules/keystore/kwallet.cpp
new file mode 100644
index 0000000..caeddb5
--- /dev/null
+++ b/modules/keystore/kwallet.cpp
@@ -0,0 +1,566 @@
+/*****************************************************************************
+ * kwallet.cpp: KWallet keystore module
+ *****************************************************************************
+ * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
+ *
+ * This program 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.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "kwallet.hpp"
+
+#include <vlc_plugin.h>
+#include <vlc_interrupt.h>
+#include <vlc_strings.h>
+
+#include <QMap>
+#include <QUrl>
+#include <QApplication>
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/qdbusservicewatcher.h>
+
+#define MAP_KEY_SECRET QString("secret")
+
+#define qfu(i) QString::fromUtf8(i)
+#define qtu(i) ((i).toUtf8().constData())
+
+static int Open(vlc_object_t *);
+static void Close(vlc_object_t *);
+
+vlc_module_begin()
+ set_shortname(N_("KWallet keystore"))
+ set_description(N_("secrets are stored via KWallet"))
+ set_category(CAT_ADVANCED)
+ set_subcategory(SUBCAT_ADVANCED_MISC)
+ set_capability("keystore", 100)
+ set_callbacks(Open, Close)
+ cannot_unload_broken_library()
+vlc_module_end ()
+
+VLCKWallet::VLCKWallet(vlc_object_t *obj)
+ : mState(STATE_INIT)
+ , mObj(obj)
+ , mWallet(NULL)
+{}
+
+static const char *const ppsz_keys[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "realm",
+ "authtype",
+};
+static_assert(sizeof(ppsz_keys)/sizeof(*ppsz_keys) == KEY_MAX, "key mismatch");
+
+static int
+str2key(const char *psz_key)
+{
+ for (unsigned int i = 0; i < KEY_MAX; ++i)
+ {
+ if (ppsz_keys[i] && strcmp(ppsz_keys[i], psz_key) == 0)
+ return i;
+ }
+ return -1;
+}
+
+void
+VLCKWallet::openWallet(bool opened)
+{
+ QMutexLocker locker(&mMutex);
+ mState = opened ? STATE_CONNECTED : STATE_DISCONNECTED;
+ mCond.wakeOne();
+}
+
+void
+VLCKWallet::closeWallet()
+{
+ QMutexLocker locker(&mMutex);
+ mState = STATE_DISCONNECTED;
+ mCond.wakeOne();
+}
+
+void
+VLCKWallet::registerService(const QString &serviceName)
+{
+ printf("VLCKWallet::registerService\n");
+ (void) serviceName;
+ QMutexLocker locker(&mMutex);
+ mState = STATE_SERVICE_ALIVE;
+ mCond.wakeOne();
+}
+
+void
+VLCKWallet::unregisterService(const QString &serviceName)
+{
+ printf("VLCKWallet::unregisterService\n");
+ (void) serviceName;
+ QMutexLocker locker(&mMutex);
+ if (mServiceCount-- == 0)
+ {
+ mState = STATE_DISCONNECTED;
+ mCond.wakeOne();
+ }
+}
+
+void
+VLCKWallet::interrupted(void *data)
+{
+ VLCKWallet *self = (VLCKWallet *) data;
+
+ self->closeWallet();
+}
+
+/**
+ * Connect to KWallet synchronously but it can be interrupted by VLC.
+ */
+bool
+VLCKWallet::connect(bool b_force)
+{
+ /* Asynchronous methods (QDBusServiceWatcher and
+ * KWallet::Wallet::Asynchronous) need a running QCoreApplication or
+ * QApplication. There can be only one and it's currently used by the qt
+ * interface. TODO: Spawn the singleton Qt thread from here or from the qt
+ * interface module */
+ if (QApplication::instance() == NULL)
+ return false;
+
+ QMutexLocker locker(&mMutex);
+
+#if 0
+ if (!b_force)
+ {
+ /* First, check if kwallet service is running using
+ * QDBusServiceWatcher. Indeed, openWallet() will spawn a service if
+ * it's not running, even on non KDE environments */
+ QDBusServiceWatcher watcher(QString::fromLatin1("org.kde.kwalletd5"),
+ QDBusConnection::sessionBus());
+ watcher.addWatchedService("org.kde.kwalletd");
+ mServiceCount = 2;
+
+ vlc_interrupt_register(interrupted, this);
+
+ if (!QObject::connect(&watcher, SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(unregisterService(QString))))
+ return false;
+ if (!QObject::connect(&watcher, SIGNAL(serviceRegistered(QString)),
+ this, SLOT(registerService(QString))))
+ return false;
+
+ while (mState == STATE_INIT)
+ mCond.wait(&mMutex);
+
+ vlc_interrupt_unregister();
+
+ if (mState != STATE_SERVICE_ALIVE)
+ return false;
+ }
+ else
+ mState = STATE_SERVICE_ALIVE;
+
+ mWallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), 0,
+ KWallet::Wallet::Asynchronous);
+ if (!mWallet)
+ {
+ msg_Err(mObj, "openWallet failed");
+ return false;
+ }
+ mWallet->setParent(this);
+
+ vlc_interrupt_register(interrupted, this);
+
+ /* Connect KWallet signals */
+ if (!QObject::connect(mWallet, SIGNAL(walletOpened(bool)),
+ this, SLOT(openWallet(bool))))
+ {
+ msg_Err(mObj, "could not connect to walletOpened");
+ return false;
+ }
+ if (!QObject::connect(mWallet, SIGNAL(walletClosed()),
+ this, SLOT(closeWallet())))
+ {
+ msg_Err(mObj, "could not connect to walletClosed");
+ return false;
+ }
+
+ /* Wait for wallet connection or vlc interrupt */
+ while (mState == STATE_SERVICE_ALIVE)
+ mCond.wait(&mMutex);
+
+ vlc_interrupt_unregister();
+#else
+ mWallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), 0,
+ KWallet::Wallet::Synchronous);
+ if (!mWallet)
+ {
+ msg_Err(mObj, "openWallet failed");
+ return false;
+ }
+ mWallet->setParent(this);
+ mState = STATE_CONNECTED;
+#endif
+
+ if (mState == STATE_CONNECTED)
+ {
+ /* Create VLC folder if it doesn't exist */
+ if (!mWallet->hasFolder(VLC_KEYSTORE_NAME))
+ {
+ if (!mWallet->createFolder(VLC_KEYSTORE_NAME))
+ {
+ msg_Err(mObj, "could not create '%s' folder'", VLC_KEYSTORE_NAME);
+ return false;
+ }
+ }
+ /* set VLC folder */
+ return mWallet->setFolder(VLC_KEYSTORE_NAME);
+ }
+ else
+ return false;
+}
+
+static int
+str2int(const char *psz_port)
+{
+ if (psz_port)
+ {
+ bool ok;
+ int i_port = qfu(psz_port).toInt(&ok);
+ if (!ok)
+ return -1;
+ return i_port;
+ }
+ else
+ return -1;
+}
+
+/**
+ * Create a key and a map from values
+ */
+static QString
+values2Key(const char * const ppsz_values[KEY_MAX])
+{
+ const char *psz_protocol = ppsz_values[KEY_PROTOCOL];
+ const char *psz_user = ppsz_values[KEY_USER];
+ const char *psz_server = ppsz_values[KEY_SERVER];
+ const char *psz_path = ppsz_values[KEY_PATH];
+ const char *psz_port = ppsz_values[KEY_PORT];
+ int i_port = str2int(psz_port);
+
+ if (!psz_protocol || !psz_user || !psz_server || !psz_path)
+ return QString();
+
+ QUrl url;
+ url.setScheme(qfu(psz_protocol));
+ url.setUserName(qfu(psz_user));
+ url.setHost(qfu(psz_server));
+ url.setPath(qfu(psz_path));
+
+ if (i_port != -1)
+ url.setPort(i_port);
+
+ if (!url.isValid())
+ return QString();
+ return url.toString();
+}
+
+static int
+key2Values(const QString &key, const char * ppsz_values[KEY_MAX])
+{
+ QUrl url(key);
+ if (!url.isValid())
+ return VLC_EGENERIC;
+
+ if (url.scheme().isEmpty() || url.userName().isEmpty()
+ || url.host().isEmpty() || url.path().isEmpty())
+ return VLC_EGENERIC;
+
+ ppsz_values[KEY_PROTOCOL] = strdup(qtu(url.scheme()));
+ ppsz_values[KEY_USER] = strdup(qtu(url.userName()));
+ ppsz_values[KEY_SERVER] = strdup(qtu(url.host()));
+ ppsz_values[KEY_PATH] = strdup(qtu(url.path()));
+
+ if (!ppsz_values[KEY_PROTOCOL] || !ppsz_values[KEY_USER]
+ || !ppsz_values[KEY_SERVER] || !ppsz_values[KEY_PATH])
+ return VLC_EGENERIC;
+
+ int i_port = url.port();
+ if (i_port != -1)
+ {
+ ppsz_values[KEY_PORT] = strdup(qtu(QString("%1").arg(i_port)));
+ if (!ppsz_values[KEY_PORT])
+ return VLC_EGENERIC;
+ }
+
+ return VLC_SUCCESS;
+}
+
+static bool
+matchKey(const QString &key, const char * const ppsz_values[KEY_MAX])
+{
+ QUrl url(key);
+ if (!url.isValid())
+ return false;
+
+ if (url.scheme().isEmpty() || url.userName().isEmpty()
+ || url.host().isEmpty() || url.path().isEmpty())
+ return false;
+
+ const char *psz_protocol = ppsz_values[KEY_PROTOCOL];
+ const char *psz_user = ppsz_values[KEY_USER];
+ const char *psz_server = ppsz_values[KEY_SERVER];
+ const char *psz_path = ppsz_values[KEY_PATH];
+ const char *psz_port = ppsz_values[KEY_PORT];
+ int i_port = str2int(psz_port);
+
+ return (!psz_protocol || strcmp(psz_protocol, qtu(url.scheme())) == 0)
+ && (!psz_user || strcmp(psz_user, qtu(url.userName())) == 0)
+ && (!psz_server || strcmp(psz_server, qtu(url.host())) == 0)
+ && (!psz_path || strcmp(psz_path, qtu(url.path())) == 0)
+ && (i_port == -1 || i_port == url.port());
+}
+
+static QMap<QString, QString>
+values2Map(const char * const ppsz_values[KEY_MAX])
+{
+ QMap<QString, QString> map;
+ for (unsigned int i = 0; i < KEY_MAX; ++i)
+ {
+ const char *psz_key = ppsz_keys[i];
+ if (psz_key && ppsz_values[i])
+ map.insert(qfu(psz_key), qfu(ppsz_values[i]));
+ }
+ return map;
+}
+
+/**
+ * Return true if all pairs of matchMap are in map (and not the contrary).
+ */
+static bool
+matchMaps(const QMap<QString, QString> &matchMap,
+ const QMap<QString, QString> &map)
+{
+ if (matchMap.isEmpty())
+ return true;
+
+ QMapIterator<QString, QString> it(matchMap);
+ while (it.hasNext())
+ {
+ it.next();
+ if (map.value(it.key()) != it.value())
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Fill a keystore entry from a map and a key
+ */
+static int
+mapAndKey2Entry(const QMap<QString, QString> &map, const QString &key,
+ vlc_keystore_entry *p_entry)
+{
+ QMapIterator<QString, QString> it(map);
+ while (it.hasNext())
+ {
+ it.next();
+ if (it.key() != MAP_KEY_SECRET)
+ {
+ /* Copy map pair to ppsz_values */
+ const char *psz_key = qtu(it.key());
+ int i_key = str2key(psz_key);
+ if (i_key == -1 || i_key >= KEY_MAX)
+ return VLC_EGENERIC;
+
+ char *psz_value = strdup(qtu(it.value()));
+ if (!psz_value)
+ return VLC_EGENERIC;
+ p_entry->ppsz_values[i_key] = psz_value;
+ }
+ else
+ {
+ /* Copy secret from the map */
+ p_entry->i_secret_len =
+ vlc_b64_decode_binary(&p_entry->p_secret,
+ it.value().toLocal8Bit().constData());
+ if (!p_entry->i_secret_len)
+ return VLC_EGENERIC;
+ }
+ }
+ return key2Values(key, (const char **)p_entry->ppsz_values);
+}
+
+int
+VLCKWallet::store(const char * const ppsz_values[KEY_MAX],
+ const uint8_t *p_secret, size_t i_secret_len,
+ const char *psz_label)
+{
+ (void) psz_label;
+ QMutexLocker locker(&mMutex);
+
+ if (mState != STATE_CONNECTED)
+ return VLC_EGENERIC;
+
+ /* Get key and map from values */
+ QString key = values2Key(ppsz_values);
+ if (key.isEmpty())
+ return VLC_EGENERIC;
+ QMap<QString, QString> map = values2Map(ppsz_values);
+
+ /* Encode secret, since KWallet can't store binary */
+ char *psz_b64_secret = vlc_b64_encode_binary(p_secret, i_secret_len);
+ if (!psz_b64_secret)
+ return VLC_EGENERIC;
+ /* Write the secret into the map */
+ map.insert(MAP_KEY_SECRET, QString(psz_b64_secret));
+ free(psz_b64_secret);
+
+ /* Write the map at the specified key */
+ if (mWallet->writeMap(key, map) != 0)
+ return VLC_EGENERIC;
+
+ return VLC_SUCCESS;
+}
+
+unsigned int
+VLCKWallet::find(const char * const ppsz_values[KEY_MAX],
+ vlc_keystore_entry **pp_entries)
+{
+ QMutexLocker locker(&mMutex);
+
+ if (mState != STATE_CONNECTED)
+ return 0;
+
+ /* Get map from values */
+ QMap<QString, QString> matchMap = values2Map(ppsz_values);
+
+ /* Fetch all maps */
+ QMap<QString, QMap<QString, QString>> mapMap;
+ if (mWallet->readMapList(QString("*"), mapMap) != 0)
+ return 0;
+
+ unsigned int i_entry_count = 0;
+ vlc_keystore_entry *p_entries = (vlc_keystore_entry *)
+ calloc(mapMap.size(), sizeof(vlc_keystore_entry));
+
+ QMapIterator<QString, QMap<QString, QString>> it(mapMap);
+ while (it.hasNext())
+ {
+ it.next();
+
+ if (!matchKey(it.key(), ppsz_values) || !matchMaps(matchMap, it.value()))
+ continue;
+
+ /* Matching key/value */
+ vlc_keystore_entry *p_entry = &p_entries[i_entry_count++];
+
+ /* Fill the entry from the map and the key */
+ if (mapAndKey2Entry(it.value(), it.key(), p_entry))
+ {
+ vlc_keystore_release_entries(p_entries, i_entry_count);
+ return 0;
+ }
+ }
+ *pp_entries = p_entries;
+ return i_entry_count;
+}
+
+unsigned int
+VLCKWallet::remove(const char * const ppsz_values[KEY_MAX])
+{
+ QMutexLocker locker(&mMutex);
+
+ if (mState != STATE_CONNECTED)
+ return 0;
+
+ QMap<QString, QString> matchMap = values2Map(ppsz_values);
+
+ /* Fetch all maps */
+ QMap<QString, QMap<QString, QString>> mapMap;
+ if (mWallet->readMapList("*", mapMap) != 0)
+ return 0;
+
+ unsigned int i_entry_count = 0;
+ QMapIterator<QString, QMap<QString, QString>> it(mapMap);
+ while (it.hasNext())
+ {
+ it.next();
+
+ if (!matchKey(it.key(), ppsz_values) || !matchMaps(matchMap, it.value()))
+ continue;
+
+ /* Matching key/value */
+ if (mWallet->removeEntry(it.key()) == 0)
+ i_entry_count++;
+ }
+ return i_entry_count;
+}
+
+static int
+Store(vlc_keystore *p_keystore, const char * const ppsz_values[KEY_MAX],
+ const uint8_t *p_secret, size_t i_secret_len, const char *psz_label)
+{
+ VLCKWallet *p_wallet = (VLCKWallet *) p_keystore->p_sys;
+
+ return p_wallet->store(ppsz_values, p_secret, i_secret_len, psz_label);
+}
+
+static unsigned int
+Find(vlc_keystore *p_keystore, const char * const ppsz_values[KEY_MAX],
+ vlc_keystore_entry **pp_entries)
+{
+ VLCKWallet *p_wallet = (VLCKWallet *) p_keystore->p_sys;
+
+ return p_wallet->find(ppsz_values, pp_entries);
+}
+
+static unsigned int
+Remove(vlc_keystore *p_keystore, const char * const ppsz_values[KEY_MAX])
+{
+ VLCKWallet *p_wallet = (VLCKWallet *) p_keystore->p_sys;
+
+ return p_wallet->remove(ppsz_values);
+}
+
+static int
+Open(vlc_object_t *p_this)
+{
+ VLCKWallet *p_wallet = new VLCKWallet(p_this);
+
+ if (!p_wallet->connect(p_this->b_force))
+ {
+ delete p_wallet;
+ return VLC_EGENERIC;
+ }
+ vlc_keystore *p_keystore = (vlc_keystore *)p_this;
+ p_keystore->p_sys = (vlc_keystore_sys *) p_wallet;
+ p_keystore->pf_store = Store;
+ p_keystore->pf_find = Find;
+ p_keystore->pf_remove = Remove;
+
+ return VLC_SUCCESS;
+}
+
+static void
+Close(vlc_object_t *p_this)
+{
+ vlc_keystore *p_keystore = (vlc_keystore *)p_this;
+ VLCKWallet *p_wallet = (VLCKWallet *) p_keystore->p_sys;
+
+ delete p_wallet;
+}
diff --git a/modules/keystore/kwallet.hpp b/modules/keystore/kwallet.hpp
new file mode 100644
index 0000000..e03c325
--- /dev/null
+++ b/modules/keystore/kwallet.hpp
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * kwallet.hpp: KWallet keystore module
+ *****************************************************************************
+ * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
+ *
+ * This program 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.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_keystore.h>
+
+#include <kwallet.h>
+#include <QObject>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QWaitCondition>
+
+class VLCKWallet : public QObject
+{
+ Q_OBJECT
+
+public:
+ VLCKWallet(vlc_object_t *obj);
+ bool connect(bool b_force);
+ int store(const char * const ppsz_values[KEY_MAX],
+ const uint8_t *p_secret, size_t i_secret_len,
+ const char *psz_label);
+ unsigned int find(const char * const ppsz_values[KEY_MAX],
+ vlc_keystore_entry **pp_entries);
+ unsigned int remove(const char * const ppsz_values[KEY_MAX]);
+
+private slots:
+ void openWallet(bool opened);
+ void closeWallet();
+ void registerService(const QString &serviceName);
+ void unregisterService(const QString &serviceName);
+
+private:
+ static void interrupted(void *data);
+
+ enum {
+ STATE_INIT,
+ STATE_SERVICE_ALIVE,
+ STATE_CONNECTED,
+ STATE_DISCONNECTED,
+ } mState;
+
+ vlc_object_t * mObj;
+ KWallet::Wallet * mWallet;
+ QMutex mMutex;
+ QWaitCondition mCond;
+ unsigned int mServiceCount;
+};
--
2.1.4
More information about the vlc-devel
mailing list