// SPDX-FileCopyrightText: 2020 Linus Jahn // // SPDX-License-Identifier: LGPL-2.1-or-later #include "QXmppPubSubSubscription.h" #include "QXmppConstants_p.h" #include "QXmppUtils.h" #include #include #include /// /// \class QXmppPubSubSubscription /// /// The QXmppPubSubSubscription class represents a PubSub subscription contained /// in event notifications and IQ requests, as defined in \xep{0060, Publish- /// Subscribe}. /// /// \ingroup Stanzas /// /// \since QXmpp 1.5 /// static const QStringList SUBSCRIPTION_STATES = { QString(), QStringLiteral("none"), QStringLiteral("pending"), QStringLiteral("subscribed"), QStringLiteral("unconfigured"), }; class QXmppPubSubSubscriptionPrivate : public QSharedData { public: QXmppPubSubSubscriptionPrivate(const QString &jid, const QString &node, const QString &subId, QXmppPubSubSubscription::State state, QXmppPubSubSubscription::ConfigurationSupport configurationSupport, const QDateTime &expiry); QString jid; QString node; QString subId; QDateTime expiry; QXmppPubSubSubscription::State state; QXmppPubSubSubscription::ConfigurationSupport configurationSupport; }; QXmppPubSubSubscriptionPrivate::QXmppPubSubSubscriptionPrivate(const QString &jid, const QString &node, const QString &subId, QXmppPubSubSubscription::State state, QXmppPubSubSubscription::ConfigurationSupport configurationSupport, const QDateTime &expiry) : jid(jid), node(node), subId(subId), expiry(expiry), state(state), configurationSupport(configurationSupport) { } /// /// Converts a subscription state to string. /// QString QXmppPubSubSubscription::stateToString(State state) { return SUBSCRIPTION_STATES.at(int(state)); } /// /// Converts a string with a subscription state to the enum value. /// QXmppPubSubSubscription::State QXmppPubSubSubscription::stateFromString(const QString &str) { if (const auto state = SUBSCRIPTION_STATES.indexOf(str); state != -1) { return State(state); } return Invalid; } /// /// Creates a new QXmppPubSubSubscription. /// /// \param jid /// \param node /// \param subId /// \param state /// \param configurationSupport /// \param expiry /// QXmppPubSubSubscription::QXmppPubSubSubscription(const QString &jid, const QString &node, const QString &subId, State state, ConfigurationSupport configurationSupport, const QDateTime &expiry) : d(new QXmppPubSubSubscriptionPrivate(jid, node, subId, state, configurationSupport, expiry)) { } /// Copy contructor. QXmppPubSubSubscription::QXmppPubSubSubscription(const QXmppPubSubSubscription &) = default; /// Move contructor. QXmppPubSubSubscription::QXmppPubSubSubscription(QXmppPubSubSubscription &&) = default; QXmppPubSubSubscription::~QXmppPubSubSubscription() = default; /// Copy assignment operator. QXmppPubSubSubscription &QXmppPubSubSubscription::operator=(const QXmppPubSubSubscription &) = default; /// Move-assignment operator. QXmppPubSubSubscription &QXmppPubSubSubscription::operator=(QXmppPubSubSubscription &&) = default; /// /// Returns the JID of the user of this subscription. /// QString QXmppPubSubSubscription::jid() const { return d->jid; } /// /// Sets the JID of the user of this subscription. /// void QXmppPubSubSubscription::setJid(const QString &jid) { d->jid = jid; } /// /// Returns the node name of this subscription. /// QString QXmppPubSubSubscription::node() const { return d->node; } /// /// Sets the node name of this subscription. /// void QXmppPubSubSubscription::setNode(const QString &node) { d->node = node; } /// /// Returns the subscription ID (may be empty). /// QString QXmppPubSubSubscription::subId() const { return d->subId; } /// /// Sets the subscription ID (may be empty). /// void QXmppPubSubSubscription::setSubId(const QString &subId) { d->subId = subId; } /// /// Returns the state of the subscription. /// QXmppPubSubSubscription::State QXmppPubSubSubscription::state() const { return d->state; } /// /// Sets the state of the subscription. /// void QXmppPubSubSubscription::setState(State state) { d->state = state; } /// /// Returns the expiry date of the subscription. /// /// If this timestamp is valid, the subscription is going to be cancelled at /// this date. /// QDateTime QXmppPubSubSubscription::expiry() const { return d->expiry; } /// /// Sets the expiry date of the subscription. /// /// If this timestamp is valid, the subscription is going to be cancelled at /// this date. /// void QXmppPubSubSubscription::setExpiry(const QDateTime &expiry) { d->expiry = expiry; } /// /// Returns the availability of a subscription configuration. /// QXmppPubSubSubscription::ConfigurationSupport QXmppPubSubSubscription::configurationSupport() const { return d->configurationSupport; } /// /// Sets the availability of a subscription configuration. /// void QXmppPubSubSubscription::setConfigurationSupport(ConfigurationSupport support) { d->configurationSupport = support; } /// /// Returns whether a configuration of the subscription is possible. /// bool QXmppPubSubSubscription::isConfigurationSupported() const { return d->configurationSupport > Unavailable; } /// /// Returns whether configuration of the subscription required before event /// notifications are going to be sent to the user. /// bool QXmppPubSubSubscription::isConfigurationRequired() const { return d->configurationSupport == Required || d->state == Unconfigured; } /// /// Returns true, if the element is a PubSub subscription element. /// bool QXmppPubSubSubscription::isSubscription(const QDomElement &element) { if (element.tagName() != QStringLiteral("subscription")) { return false; } if (element.hasAttribute(QStringLiteral("subscription"))) { const auto subStateStr = element.attribute(QStringLiteral("subscription")); if (!SUBSCRIPTION_STATES.contains(subStateStr)) { return false; } } if (element.namespaceURI() == ns_pubsub || element.namespaceURI() == ns_pubsub_event) { return element.hasAttribute(QStringLiteral("jid")); } if (element.namespaceURI() == ns_pubsub_owner) { return element.hasAttribute(QStringLiteral("jid")) && element.hasAttribute(QStringLiteral("subscription")); } return false; } /// \cond void QXmppPubSubSubscription::parse(const QDomElement &element) { bool isPubSub = element.namespaceURI() == ns_pubsub; bool isPubSubEvent = !isPubSub && element.namespaceURI() == ns_pubsub_event; d->jid = element.attribute(QStringLiteral("jid")); d->state = stateFromString(element.attribute(QStringLiteral("subscription"))); if (isPubSub || isPubSubEvent) { d->node = element.attribute(QStringLiteral("node")); d->subId = element.attribute(QStringLiteral("subid")); if (isPubSubEvent) { if (element.hasAttribute(QStringLiteral("expiry"))) { d->expiry = QXmppUtils::datetimeFromString( element.attribute(QStringLiteral("expiry"))); } } else if (isPubSub) { auto options = element.firstChildElement(QStringLiteral("subscribe-options")); if (options.isNull()) { d->configurationSupport = Unavailable; } else { if (!options.firstChildElement(QStringLiteral("required")).isNull()) { d->configurationSupport = Required; } else { d->configurationSupport = Available; } } } } } void QXmppPubSubSubscription::toXml(QXmlStreamWriter *writer) const { writer->writeStartElement(QStringLiteral("subscription")); // jid is required writer->writeAttribute(QStringLiteral("jid"), d->jid); helperToXmlAddAttribute(writer, QStringLiteral("node"), d->node); helperToXmlAddAttribute(writer, QStringLiteral("subscription"), stateToString(d->state)); helperToXmlAddAttribute(writer, QStringLiteral("subid"), d->subId); if (d->expiry.isValid()) { writer->writeAttribute(QStringLiteral("expiry"), QXmppUtils::datetimeToString(d->expiry)); } if (d->configurationSupport > Unavailable) { writer->writeStartElement(QStringLiteral("subscribe-options")); if (d->configurationSupport == Required) { writer->writeEmptyElement(QStringLiteral("required")); } writer->writeEndElement(); } writer->writeEndElement(); } /// \endcond