From 9b21bef379d94876908cbb706c9ba2438779bf54 Mon Sep 17 00:00:00 2001 From: Linus Jahn Date: Wed, 29 Sep 2021 13:15:53 +0200 Subject: PubSubManager: Add node configuration requests --- src/client/QXmppPubSubManager.cpp | 146 +++++++++++++++++++++++++++++++++++--- src/client/QXmppPubSubManager.h | 7 ++ 2 files changed, 145 insertions(+), 8 deletions(-) (limited to 'src/client') diff --git a/src/client/QXmppPubSubManager.cpp b/src/client/QXmppPubSubManager.cpp index c28df7f3..08fe75e7 100644 --- a/src/client/QXmppPubSubManager.cpp +++ b/src/client/QXmppPubSubManager.cpp @@ -24,19 +24,19 @@ #include "QXmppPubSubManager.h" -#include -#include - #include "QXmppClient.h" #include "QXmppConstants_p.h" -#include "QXmppPubSubItem.h" -#include "QXmppPubSubEventManager.h" -#include "QXmppPubSubSubscription.h" #include "QXmppPubSubAffiliation.h" +#include "QXmppPubSubEventManager.h" +#include "QXmppPubSubItem.h" #include "QXmppPubSubSubscribeOptions.h" +#include "QXmppPubSubSubscription.h" #include "QXmppStanza.h" #include "QXmppUtils.h" +#include +#include + using namespace QXmpp::Private; /// @@ -158,6 +158,13 @@ using namespace QXmpp::Private; /// returned IQ error (QXmppStanza::Error). /// +/// +/// \typedef QXmppPubSubManager::NodeConfigResult +/// +/// Contains a node configuration (QXmppPubSubNodeConfig) or the returned IQ +/// error (QXmppStanza::Error). +/// + /// /// Default constructor. /// @@ -280,7 +287,7 @@ auto QXmppPubSubManager::retractItem(const QString &jid, const QString &nodeName request.setType(QXmppIq::Set); request.setQueryType(QXmppPubSubIq<>::Retract); request.setQueryNode(nodeName); - request.setItems({QXmppPubSubItem(itemId)}); + request.setItems({ QXmppPubSubItem(itemId) }); request.setTo(jid); return client()->sendGenericIq(std::move(request)); @@ -472,6 +479,87 @@ QFuture QXmppPubSubManager::setSubscribeOptions(cons return client()->sendGenericIq(std::move(request)); } +/// +/// Requests the node configuration and starts the configuration process. +/// +/// Requires owner privileges. If the result is successful (a node config form +/// has been returned) this starts the configuration process. The next step is +/// to call configureNode() or cancelNodeConfiguration(). +/// +/// \param service JID of the pubsub service +/// \param nodeName Name of the pubsub node on the service +/// \return +/// +/// \sa configureNode() +/// \sa cancelNodeConfiguration() +/// +QFuture QXmppPubSubManager::requestNodeConfiguration(const QString &service, const QString &nodeName) +{ + using Error = QXmppStanza::Error; + + QXmppPubSubIq request; + request.setType(QXmppIq::Get); + request.setTo(service); + request.setQueryNode(nodeName); + request.setQueryType(QXmppPubSubIq<>::Configure); + + return chainIq(client()->sendIq(std::move(request)), this, + [](QXmppPubSubIq<> &&iq) -> NodeConfigResult { + if (const auto dataForm = iq.dataForm()) { + if (const auto config = QXmppPubSubNodeConfig::fromDataForm(*dataForm)) { + return *config; + } + return Error(Error::Cancel, Error::UndefinedCondition, QStringLiteral("Server returned invalid data form.")); + } + return Error(Error::Cancel, Error::UndefinedCondition, QStringLiteral("Server returned no data form.")); + }); +} + +/// +/// Sets a node configuration. +/// +/// Requires owner privileges. You can use requestNodeConfiguration() to receive +/// a data form with all valid options and default values. +/// +/// \param service JID of the pubsub service +/// \param nodeName Name of the pubsub node on the service +/// \param config +/// \return +/// +/// \sa requestNodeConfiguration() +/// +QFuture QXmppPubSubManager::configureNode(const QString &service, const QString &nodeName, const QXmppPubSubNodeConfig &config) +{ + QXmppPubSubIq request; + request.setType(QXmppIq::Set); + request.setTo(service); + request.setQueryNode(nodeName); + request.setQueryType(QXmppPubSubIq<>::Configure); + request.setDataForm(config); + return client()->sendGenericIq(std::move(request)); +} + +/// +/// Cancels the configuration process and uses the default or exisiting +/// configuration. +/// +/// \param service JID of the pubsub service +/// \param nodeName Name of the pubsub node on the service +/// \return +/// +/// \sa requestNodeConfiguration() +/// +QFuture QXmppPubSubManager::cancelNodeConfiguration(const QString &service, const QString &nodeName) +{ + QXmppPubSubIq request; + request.setType(QXmppIq::Set); + request.setTo(service); + request.setQueryNode(nodeName); + request.setQueryType(QXmppPubSubIq<>::Configure); + request.setDataForm(QXmppDataForm(QXmppDataForm::Cancel)); + return client()->sendGenericIq(std::move(request)); +} + /// /// \fn QXmppPubSubManager::createPepNode /// @@ -527,6 +615,48 @@ QFuture QXmppPubSubManager::setSubscribeOptions(cons /// \return /// +/// +/// \fn QXmppPubSubManager::requestPepNodeConfiguration +/// +/// Requests the node configuration and starts the configuration process. +/// +/// This is a convenience method equivalent to calling +/// requestNodeConfiguration() the current account's bare JID. +/// +/// \param nodeName Name of the pubsub node on the service +/// \return +/// +/// \sa configurePepNode() +/// \sa cancelPepNodeConfiguration() +/// + +/// +/// \fn QXmppPubSubManager::configurePepNode +/// +/// Sets a node configuration. +/// +/// This is a convenience method equivalent to calling configureNode() the +/// current account's bare JID. +/// +/// \param nodeName Name of the pubsub node on the service +/// \param config +/// \return +/// +/// \sa requestPepNodeConfiguration() +/// + +/// +/// \fn QXmppPubSubManager::cancelPepNodeConfiguration +/// +/// This is a convenience method equivalent to calling cancelNodeConfiguration() +/// the current account's bare JID. +/// +/// \param nodeName Name of the pubsub node on the service +/// \return +/// +/// \sa requestPepNodeConfiguration() +/// + /// \cond QStringList QXmppPubSubManager::discoveryFeatures() const { @@ -549,7 +679,7 @@ bool QXmppPubSubManager::handleStanza(const QDomElement &element) const auto extensions = client()->extensions(); for (auto *extension : extensions) { - if (auto *eventManager = qobject_cast(extension)) { + if (auto *eventManager = qobject_cast(extension)) { if (eventManager->handlePubSubEvent(element, service, node)) { return true; } diff --git a/src/client/QXmppPubSubManager.h b/src/client/QXmppPubSubManager.h index 26ff7aaf..f3798a3f 100644 --- a/src/client/QXmppPubSubManager.h +++ b/src/client/QXmppPubSubManager.h @@ -62,6 +62,7 @@ public: using SubscriptionsResult = std::variant, QXmppStanza::Error>; using AffiliationsResult = std::variant, QXmppStanza::Error>; using OptionsResult = std::variant; + using NodeConfigResult = std::variant; QXmppPubSubManager(); ~QXmppPubSubManager(); @@ -96,6 +97,9 @@ public: QFuture requestSubscribeOptions(const QString &service, const QString &nodeName, const QString &subscriberJid); QFuture setSubscribeOptions(const QString &service, const QString &nodeName, const QXmppPubSubSubscribeOptions &options); QFuture setSubscribeOptions(const QString &service, const QString &nodeName, const QXmppPubSubSubscribeOptions &options, const QString &subscriberJid); + QFuture requestNodeConfiguration(const QString &service, const QString &nodeName); + QFuture configureNode(const QString &service, const QString &nodeName, const QXmppPubSubNodeConfig &config); + QFuture cancelNodeConfiguration(const QString &service, const QString &nodeName); // PEP-specific (the PubSub service is the current account) inline QFuture createPepNode(const QString &nodeName) { return createNode(client()->configuration().jidBare(), nodeName); } @@ -110,6 +114,9 @@ public: QFuture publishPepItems(const QString &nodeName, const QVector &items); inline QFuture retractPepItem(const QString &nodeName, const QString &itemId) { return retractItem(client()->configuration().jidBare(), nodeName, itemId); } inline QFuture purgePepItems(const QString &nodeName) { return purgeItems(client()->configuration().jidBare(), nodeName); } + inline QFuture requestPepNodeConfiguration(const QString &nodeName) { return requestNodeConfiguration(client()->configuration().jidBare(), nodeName); } + inline QFuture configurePepNode(const QString &nodeName, const QXmppPubSubNodeConfig &config) { return configureNode(client()->configuration().jidBare(), nodeName, config); } + inline QFuture cancelPepNodeConfiguration(const QString &nodeName) { return cancelNodeConfiguration(client()->configuration().jidBare(), nodeName); } /// \cond QStringList discoveryFeatures() const override; -- cgit v1.2.3