aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJBB <jbb.prv@gmx.de>2020-03-29 21:40:17 +0200
committerGitHub <noreply@github.com>2020-03-29 21:40:17 +0200
commit13870274bba1765a1fcecedb5bcc0eda8db682eb (patch)
treeff8c15af87084dd8829e87de73fbf9f03e50cf74
parent1476fa153260487a6ddbc742ca6fdc4054ffd88a (diff)
downloadqxmpp-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.doc1
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/base/QXmppConstants.cpp2
-rw-r--r--src/base/QXmppConstants_p.h2
-rw-r--r--src/base/QXmppPushEnableIq.cpp179
-rw-r--r--src/base/QXmppPushEnableIq.h76
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/qxmpppushenableiq/tst_qxmpppushenableiq.cpp173
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"