diff options
| author | JBB <jbb.prv@gmx.de> | 2020-03-29 21:40:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-29 21:40:17 +0200 |
| commit | 13870274bba1765a1fcecedb5bcc0eda8db682eb (patch) | |
| tree | ff8c15af87084dd8829e87de73fbf9f03e50cf74 | |
| parent | 1476fa153260487a6ddbc742ca6fdc4054ffd88a (diff) | |
| download | qxmpp-13870274bba1765a1fcecedb5bcc0eda8db682eb.tar.gz | |
Implement XEP-0357: Push Notifications enable/disable IQ (#271)
Co-authored-by: Robert Maerkisch <zatroxde@protonmail.ch>
Co-authored-by: Linus Jahn <lnj@kaidan.im>
| -rw-r--r-- | doc/xep.doc | 1 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/base/QXmppConstants.cpp | 2 | ||||
| -rw-r--r-- | src/base/QXmppConstants_p.h | 2 | ||||
| -rw-r--r-- | src/base/QXmppPushEnableIq.cpp | 179 | ||||
| -rw-r--r-- | src/base/QXmppPushEnableIq.h | 76 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tests/qxmpppushenableiq/tst_qxmpppushenableiq.cpp | 173 |
8 files changed, 436 insertions, 0 deletions
diff --git a/doc/xep.doc b/doc/xep.doc index d6d3cf6c..7d2d77a8 100644 --- a/doc/xep.doc +++ b/doc/xep.doc @@ -44,6 +44,7 @@ Complete: - XEP-0319: Last User Interaction in Presence - XEP-0334: Message Processing Hints (v0.3) - XEP-0352: Client State Indication +- XEP-0357: Push Notifications (v0.4) (partially) - XEP-0359: Unique and Stable Stanza IDs (v0.6) - XEP-0363: HTTP File Upload (v1.0) - XEP-0367: Message Attaching (v0.3) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 489ccd0b..3ca3f85e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,6 +43,7 @@ set(INSTALL_HEADER_FILES base/QXmppPresence.h base/QXmppPubSubIq.h base/QXmppPubSubItem.h + base/QXmppPushEnableIq.h base/QXmppRegisterIq.h base/QXmppResultSet.h base/QXmppRosterIq.h @@ -123,6 +124,7 @@ set(SOURCE_FILES base/QXmppPresence.cpp base/QXmppPubSubIq.cpp base/QXmppPubSubItem.cpp + base/QXmppPushEnableIq.cpp base/QXmppRegisterIq.cpp base/QXmppResultSet.cpp base/QXmppRosterIq.cpp diff --git a/src/base/QXmppConstants.cpp b/src/base/QXmppConstants.cpp index bd813ea6..9cfd532c 100644 --- a/src/base/QXmppConstants.cpp +++ b/src/base/QXmppConstants.cpp @@ -139,6 +139,8 @@ const char* ns_chat_markers = "urn:xmpp:chat-markers:0"; const char* ns_message_processing_hints = "urn:xmpp:hints"; // XEP-0352: Client State Indication const char* ns_csi = "urn:xmpp:csi:0"; +// XEP-0357: Push Notifications +const char* ns_push = "urn:xmpp:push:0"; // XEP-0359: Unique and Stable Stanza IDs const char* ns_sid = "urn:xmpp:sid:0"; // XEP-0363: HTTP File Upload diff --git a/src/base/QXmppConstants_p.h b/src/base/QXmppConstants_p.h index 23b0fcdd..3cc2ca67 100644 --- a/src/base/QXmppConstants_p.h +++ b/src/base/QXmppConstants_p.h @@ -151,6 +151,8 @@ extern const char* ns_chat_markers; extern const char* ns_message_processing_hints; // XEP-0352: Client State Indication extern const char* ns_csi; +// XEP-0357: Push Notifications +extern const char* ns_push; // XEP-0359: Unique and Stable Stanza IDs extern const char* ns_sid; // XEP-0363: HTTP File Upload diff --git a/src/base/QXmppPushEnableIq.cpp b/src/base/QXmppPushEnableIq.cpp new file mode 100644 index 00000000..f367566e --- /dev/null +++ b/src/base/QXmppPushEnableIq.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2008-2020 The QXmpp developers + * + * Author: + * Robert Märkisch + * Linus Jahn + * Jonah Brüchert + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * 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.1 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. + * + */ + +#include "QXmppPushEnableIq.h" + +#include "QXmppConstants_p.h" +#include "QXmppDataForm.h" + +#include <QDomElement> + +class QXmppPushEnableIqPrivate : public QSharedData +{ +public: + QString node; + QString jid; + QXmppPushEnableIq::Mode mode; + QXmppDataForm dataForm; +}; + +QXmppPushEnableIq::QXmppPushEnableIq() + : d(new QXmppPushEnableIqPrivate()) +{ +} + +QXmppPushEnableIq::QXmppPushEnableIq(const QXmppPushEnableIq &) = default; +QXmppPushEnableIq::~QXmppPushEnableIq() = default; +QXmppPushEnableIq &QXmppPushEnableIq::operator=(const QXmppPushEnableIq &) = default; + +/// +/// \brief Returns the jid of the app server +/// +QString QXmppPushEnableIq::jid() const +{ + return d->jid; +} + +/// +/// \brief Sets the jid of the app server +/// +void QXmppPushEnableIq::setJid(const QString &jid) +{ + d->jid = jid; +} + +/// +/// \brief Returns the pubsub node on the app server used by the IQ +/// +QString QXmppPushEnableIq::node() const +{ + return d->node; +} + +/// +/// \brief Set the pubsub note on the app server to be used by the IQ +/// +void QXmppPushEnableIq::setNode(const QString &node) +{ + d->node = node; +} + +/// +/// \brief Returns the mode +/// +QXmppPushEnableIq::Mode QXmppPushEnableIq::mode() +{ + return d->mode; +} + +/// +/// \brief Set whether the IQ should enable or disable push notifications +/// +void QXmppPushEnableIq::setMode(QXmppPushEnableIq::Mode mode) +{ + d->mode = mode; +} + +/// +/// \brief Returns the data form containing the publish options which the user +/// server Should send to the app server. +/// +/// It is only available for enable IQs. +/// +QXmppDataForm QXmppPushEnableIq::dataForm() const +{ + return d->dataForm; +} + +/// +/// \brief Sets the data form containing the publish options which the user +/// server Should send to the app server. +/// +/// It should only be set for enable IQs. +/// +void QXmppPushEnableIq::setDataForm(const QXmppDataForm &form) +{ + d->dataForm = form; +} + +/// +/// \brief Checks whether a QDomElement is a push notification enable / disable +/// IQ. +/// +bool QXmppPushEnableIq::isPushEnableIq(const QDomElement &element) +{ + auto childElement = element.firstChildElement(); + return childElement.namespaceURI() == ns_push && + (childElement.tagName() == QStringLiteral("enable") || childElement.tagName() == QStringLiteral("disable")); +} + +/// \cond +void QXmppPushEnableIq::parseElementFromChild(const QDomElement &element) +{ + QDomElement childElement = element.firstChildElement(); + while (!childElement.isNull()) { + if (childElement.namespaceURI() == ns_push) { + if (childElement.tagName() == QStringLiteral("enable")) { + d->mode = Enable; + + auto dataFormElement = childElement.firstChildElement("x"); + if (!dataFormElement.isNull() && dataFormElement.namespaceURI() == ns_data) { + QXmppDataForm dataForm; + dataForm.parse(dataFormElement); + d->dataForm = dataForm; + } + } else { + d->mode = Disable; + } + d->jid = childElement.attribute(QStringLiteral("jid")); + d->node = childElement.attribute(QStringLiteral("node")); + break; + } + + childElement = childElement.nextSiblingElement(); + } +} + +void QXmppPushEnableIq::toXmlElementFromChild(QXmlStreamWriter *writer) const +{ + switch (d->mode) { + case Enable: + writer->writeStartElement(QStringLiteral("enable")); + break; + case Disable: + writer->writeStartElement(QStringLiteral("disable")); + break; + } + + writer->writeDefaultNamespace(ns_push); + writer->writeAttribute(QStringLiteral("jid"), d->jid); + writer->writeAttribute(QStringLiteral("node"), d->node); + + if (d->mode == Enable) { + d->dataForm.toXml(writer); + } + writer->writeEndElement(); +} +/// \endcond diff --git a/src/base/QXmppPushEnableIq.h b/src/base/QXmppPushEnableIq.h new file mode 100644 index 00000000..d6bd0735 --- /dev/null +++ b/src/base/QXmppPushEnableIq.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008-2020 The QXmpp developers + * + * Author: + * Robert Märkisch + * Linus Jahn + * Jonah Brüchert + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * 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.1 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. + * + */ + +#pragma once + +#include <QXmppIq.h> + +class QXmppPushEnableIqPrivate; +class QXmppDataForm; + +/// +/// \brief This class represents an IQ to enable or disablepush notifications +/// on the user server. +/// +class QXMPP_EXPORT QXmppPushEnableIq : public QXmppIq +{ +public: + QXmppPushEnableIq(); + QXmppPushEnableIq(const QXmppPushEnableIq &); + ~QXmppPushEnableIq(); + QXmppPushEnableIq &operator=(const QXmppPushEnableIq &); + + /// + /// \brief The Mode enum describes whether the IQ should enable or disable + /// push notifications + /// + enum Mode : bool { + Enable = true, + Disable = false + }; + + QString jid() const; + void setJid(const QString &jid); + + QString node() const; + void setNode(const QString &node); + + void setMode(Mode mode); + Mode mode(); + + QXmppDataForm dataForm() const; + void setDataForm(const QXmppDataForm &form); + + static bool isPushEnableIq(const QDomElement &element); + +protected: + /// \cond + void parseElementFromChild(const QDomElement &element) override; + void toXmlElementFromChild(QXmlStreamWriter *writer) const override; + /// \endcond + +private: + QSharedDataPointer<QXmppPushEnableIqPrivate> d; +}; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0c0fe147..0f81c6e5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,6 +33,7 @@ add_simple_test(qxmppmessage) add_simple_test(qxmppmessagereceiptmanager) add_simple_test(qxmppmixiq) add_simple_test(qxmppnonsaslauthiq) +add_simple_test(qxmpppushenableiq) add_simple_test(qxmpppresence) add_simple_test(qxmpppubsubiq) add_simple_test(qxmppregisteriq) diff --git a/tests/qxmpppushenableiq/tst_qxmpppushenableiq.cpp b/tests/qxmpppushenableiq/tst_qxmpppushenableiq.cpp new file mode 100644 index 00000000..f45c0333 --- /dev/null +++ b/tests/qxmpppushenableiq/tst_qxmpppushenableiq.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008-2020 The QXmpp developers + * + * Author: + * Jonah Brüchert + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * 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.1 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. + * + */ + +#include <QObject> +#include "util.h" +#include <QXmppPushEnableIq.h> +#include <QXmppDataForm.h> + +class tst_QXmppPushEnableIq : public QObject +{ + Q_OBJECT + +private slots: + void testPushEnable(); + void testPushDisable(); + void testXmlNs(); + void testDataForm(); + void testIsEnableIq(); +}; + +void tst_QXmppPushEnableIq::testPushEnable() +{ + const QByteArray xml( + R"(<iq id="x42" type="set">)" + R"(<enable xmlns="urn:xmpp:push:0" jid="push-5.client.example" node="yxs32uqsflafdk3iuqo"/>)" + "</iq>"); + + QXmppPushEnableIq iq; + parsePacket(iq, xml); + QCOMPARE(iq.mode(), QXmppPushEnableIq::Enable); + QCOMPARE(iq.jid(), "push-5.client.example"); + QCOMPARE(iq.node(), "yxs32uqsflafdk3iuqo"); + + serializePacket(iq, xml); + + QXmppPushEnableIq sIq; + sIq.setJid("push-5.client.example"); + sIq.setMode(QXmppPushEnableIq::Enable); + sIq.setNode("yxs32uqsflafdk3iuqo"); + sIq.setType(QXmppIq::Set); + sIq.setId("x42"); + + serializePacket(sIq, xml); +} + +void tst_QXmppPushEnableIq::testPushDisable() +{ + const QByteArray xml( + R"(<iq id="x97" type="set">)" + R"(<disable xmlns="urn:xmpp:push:0" jid="push-5.client.example" node="yxs32uqsflafdk3iuqo"/>)" + "</iq>"); + + QXmppPushEnableIq iq; + parsePacket(iq, xml); + QCOMPARE(iq.mode(), QXmppPushEnableIq::Disable); + QCOMPARE(iq.jid(), "push-5.client.example"); + + serializePacket(iq, xml); + + QXmppPushEnableIq sIq; + sIq.setJid("push-5.client.example"); + sIq.setMode(QXmppPushEnableIq::Disable); + sIq.setNode("yxs32uqsflafdk3iuqo"); + sIq.setType(QXmppIq::Set); + sIq.setId("x97"); + + serializePacket(sIq, xml); +} + +void tst_QXmppPushEnableIq::testXmlNs() +{ + const QByteArray xml( + R"(<iq type="set" id="x97">)" + R"(<disable xmlns="urn:ympp:wrongns:0" jid="push-5.client.example"/>)" + "</iq>"); + + QXmppPushEnableIq iq; + parsePacket(iq, xml); + QVERIFY(iq.jid().isEmpty()); +} + +void tst_QXmppPushEnableIq::testDataForm() +{ + const QByteArray xml( + R"(<iq id="x43" type="set">)" + R"(<enable xmlns="urn:xmpp:push:0" jid="push-5.client.example" node="yxs32uqsflafdk3iuqo">)" + R"(<x xmlns="jabber:x:data" type="submit">)" + R"(<field type="hidden" var="FORM_TYPE"><value>http://jabber.org/protocol/pubsub#publish-options</value></field>)" + R"(<field type="text-single" var="secret"><value>eruio234vzxc2kla-91</value></field>)" + "</x>" + "</enable>" + "</iq>"); + + QXmppPushEnableIq iq; + parsePacket(iq, xml); + QVERIFY(!iq.dataForm().isNull()); + QCOMPARE(iq.dataForm().fields().size(), 2); + + serializePacket(iq, xml); + + QXmppPushEnableIq sIq; + + QXmppDataForm::Field field0; + field0.setKey("FORM_TYPE"); + field0.setType(QXmppDataForm::Field::HiddenField); + field0.setValue("http://jabber.org/protocol/pubsub#publish-options"); + + QXmppDataForm::Field field1; + field1.setKey("secret"); + field1.setValue("eruio234vzxc2kla-91"); + + QXmppDataForm form; + form.setType(QXmppDataForm::Submit); + form.setFields({field0, field1}); + + sIq.setDataForm(form); + + sIq.setType(QXmppIq::Set); + sIq.setMode(QXmppPushEnableIq::Enable); + sIq.setId("x43"); + sIq.setJid("push-5.client.example"); + sIq.setNode("yxs32uqsflafdk3iuqo"); + + serializePacket(sIq, xml); +} + +void tst_QXmppPushEnableIq::testIsEnableIq() +{ + const QByteArray xml( + R"(<iq id="x42" type="set">)" + R"(<enable xmlns="urn:xmpp:push:0" jid="push-5.client.example" node="yxs32uqsflafdk3iuqo"/>)" + "</iq>"); + + QDomDocument doc; + doc.setContent(xml, true); + bool isPushEnable = QXmppPushEnableIq::isPushEnableIq(doc.documentElement()); + QCOMPARE(isPushEnable, true); + + // reset + isPushEnable = false; + + const QByteArray xml2( + R"(<iq id="x97" type="set">)" + R"(<disable xmlns="urn:xmpp:push:0" jid="push-5.client.example" node="yxs32uqsflafdk3iuqo"/>)" + "</iq>"); + + doc.setContent(xml2, true); + isPushEnable = QXmppPushEnableIq::isPushEnableIq(doc.documentElement()); + QCOMPARE(isPushEnable, true); +} + +QTEST_MAIN(tst_QXmppPushEnableIq); +#include "tst_qxmpppushenableiq.moc" |
