aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNiels Ole Salscheider <niels_ole@salscheider-online.de>2016-11-20 12:48:26 +0100
committerJeremy Lainé <jeremy.laine@m4x.org>2017-04-29 16:09:30 +0200
commit81691141d4ac136744f2520ca41f45e281902114 (patch)
treed750c853694312913c6b5e23c9373c99585cdc85 /src
parent084eb01fb395488a0a3aee799be2b72ce11aa220 (diff)
downloadqxmpp-81691141d4ac136744f2520ca41f45e281902114.tar.gz
Add QXmppMamManager (XEP-0313)
Diffstat (limited to 'src')
-rw-r--r--src/base/QXmppConstants.cpp4
-rw-r--r--src/base/QXmppConstants_p.h4
-rw-r--r--src/base/QXmppMamIq.cpp195
-rw-r--r--src/base/QXmppMamIq.h83
-rw-r--r--src/base/base.pri2
-rw-r--r--src/client/QXmppMamManager.cpp141
-rw-r--r--src/client/QXmppMamManager.h75
-rw-r--r--src/client/client.pri2
8 files changed, 506 insertions, 0 deletions
diff --git a/src/base/QXmppConstants.cpp b/src/base/QXmppConstants.cpp
index 323b77f5..7813b144 100644
--- a/src/base/QXmppConstants.cpp
+++ b/src/base/QXmppConstants.cpp
@@ -118,5 +118,9 @@ const char* ns_bob = "urn:xmpp:bob";
const char* ns_conference = "jabber:x:conference";
// XEP-0280: Message Carbons
const char* ns_carbons = "urn:xmpp:carbons:2";
+// XEP-0297: Stanza Forwarding
+const char* ns_forwarding = "urn:xmpp:forward:0";
+// XEP-0313: Message Archive Management
+const char* ns_mam = "urn:xmpp:mam:1";
// XEP-0333: Chat Markers
const char* ns_chat_markers = "urn:xmpp:chat-markers:0";
diff --git a/src/base/QXmppConstants_p.h b/src/base/QXmppConstants_p.h
index c4cddeb8..853f8222 100644
--- a/src/base/QXmppConstants_p.h
+++ b/src/base/QXmppConstants_p.h
@@ -130,6 +130,10 @@ extern const char* ns_bob;
extern const char* ns_conference;
// XEP-0280: Message Carbons
extern const char* ns_carbons;
+// XEP-0297: Stanza Forwarding
+extern const char* ns_forwarding;
+// XEP-0313: Message Archive Management
+extern const char* ns_mam;
// XEP-0333: Char Markers
extern const char* ns_chat_markers;
diff --git a/src/base/QXmppMamIq.cpp b/src/base/QXmppMamIq.cpp
new file mode 100644
index 00000000..8b85badc
--- /dev/null
+++ b/src/base/QXmppMamIq.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2016-2017 The QXmpp developers
+ *
+ * Author:
+ * Niels Ole Salscheider
+ *
+ * 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 <QDomElement>
+
+#include "QXmppMamIq.h"
+#include "QXmppConstants_p.h"
+
+QXmppMamQueryIq::QXmppMamQueryIq() : QXmppIq(QXmppIq::Set)
+{
+}
+
+/// Returns the form that specifies the query.
+QXmppDataForm QXmppMamQueryIq::form() const
+{
+ return m_form;
+}
+
+/// Sets the data form that specifies the query.
+///
+/// \param form The data form.
+void QXmppMamQueryIq::setForm(const QXmppDataForm &form)
+{
+ m_form = form;
+}
+
+/// Returns the result set query for result set management.
+QXmppResultSetQuery QXmppMamQueryIq::resultSetQuery() const
+{
+ return m_resultSetQuery;
+}
+
+/// Sets the result set query for result set management.
+///
+/// \param resultSetQuery The result set query.
+void QXmppMamQueryIq::setResultSetQuery(const QXmppResultSetQuery &resultSetQuery)
+{
+ m_resultSetQuery = resultSetQuery;
+}
+
+/// Returns the node to query.
+QString QXmppMamQueryIq::node() const
+{
+ return m_node;
+}
+
+/// Sets the node to query.
+///
+/// \param node The node to query.
+void QXmppMamQueryIq::setNode(const QString &node)
+{
+ m_node = node;
+}
+
+/// Returns the queryid that will be included in the results.
+QString QXmppMamQueryIq::queryId() const
+{
+ return m_queryId;
+}
+
+/// Sets the queryid that will be included in the results.
+///
+/// \param id The query id.
+void QXmppMamQueryIq::setQueryId(const QString &id)
+{
+ m_queryId = id;
+}
+
+/// \cond
+bool QXmppMamQueryIq::isMamQueryIq(const QDomElement &element)
+{
+ if (element.tagName() == "iq") {
+ QDomElement queryElement = element.firstChildElement("query");
+ if (!queryElement.isNull() && queryElement.namespaceURI() == ns_mam) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void QXmppMamQueryIq::parseElementFromChild(const QDomElement &element)
+{
+ QDomElement queryElement = element.firstChildElement("query");
+ m_node = queryElement.attribute("node");
+ m_queryId = queryElement.attribute("queryId");
+ QDomElement resultSetElement = queryElement.firstChildElement("set");
+ if (!resultSetElement.isNull()) {
+ m_resultSetQuery.parse(resultSetElement);
+ }
+ QDomElement formElement = queryElement.firstChildElement("x");
+ if (!formElement.isNull()) {
+ m_form.parse(formElement);
+ }
+}
+
+void QXmppMamQueryIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("query");
+ writer->writeAttribute("xmlns", ns_mam);
+ if (!m_node.isEmpty()) {
+ writer->writeAttribute("node", m_node);
+ }
+ if (!m_queryId.isEmpty()) {
+ writer->writeAttribute("queryid", m_queryId);
+ }
+ m_form.toXml(writer);
+ m_resultSetQuery.toXml(writer);
+ writer->writeEndElement();
+}
+/// \endcond
+
+
+QXmppMamResultIq::QXmppMamResultIq() : m_complete(false)
+{
+}
+
+/// Returns the result set reply for result set management.
+QXmppResultSetReply QXmppMamResultIq::resultSetReply() const
+{
+ return m_resultSetReply;
+}
+
+/// Sets the result set reply for result set management
+void QXmppMamResultIq::setResultSetReply(const QXmppResultSetReply &resultSetReply)
+{
+ m_resultSetReply = resultSetReply;
+}
+
+/// Returns true if the results returned by the server are complete (not
+/// limited by the server).
+bool QXmppMamResultIq::complete() const
+{
+ return m_complete;
+}
+
+/// Sets if the results returned by the server are complete (not limited by the
+/// server).
+void QXmppMamResultIq::setComplete(bool complete)
+{
+ m_complete = complete;
+}
+
+/// \cond
+bool QXmppMamResultIq::isMamResultIq(const QDomElement &element)
+{
+ if (element.tagName() == "iq") {
+ QDomElement finElement = element.firstChildElement("fin");
+ if (!finElement.isNull() && finElement.namespaceURI() == ns_mam) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void QXmppMamResultIq::parseElementFromChild(const QDomElement &element)
+{
+ QDomElement finElement = element.firstChildElement("fin");
+ m_complete = finElement.attribute("complete") == QString("true");
+ QDomElement resultSetElement = finElement.firstChildElement("set");
+ if (!resultSetElement.isNull()) {
+ m_resultSetReply.parse(resultSetElement);
+ }
+}
+
+void QXmppMamResultIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("fin");
+ writer->writeAttribute("xmlns", ns_mam);
+ if (m_complete) {
+ writer->writeAttribute("complete", "true");
+ }
+ m_resultSetReply.toXml(writer);
+ writer->writeEndElement();
+}
+/// \endcond
diff --git a/src/base/QXmppMamIq.h b/src/base/QXmppMamIq.h
new file mode 100644
index 00000000..6c0d2807
--- /dev/null
+++ b/src/base/QXmppMamIq.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016-2017 The QXmpp developers
+ *
+ * Author:
+ * Niels Ole Salscheider
+ *
+ * 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.
+ *
+ */
+
+#ifndef QXMPPMAMIQ_H
+#define QXMPPMAMIQ_H
+
+#include "QXmppIq.h"
+#include "QXmppDataForm.h"
+#include "QXmppResultSet.h"
+
+/// \brief The QXmppMamQueryIq class represents the query IQ for
+/// XEP-0313: Message Archive Management.
+class QXmppMamQueryIq : public QXmppIq
+{
+public:
+ QXmppMamQueryIq();
+
+ QXmppDataForm form() const;
+ void setForm(const QXmppDataForm &form);
+ QXmppResultSetQuery resultSetQuery() const;
+ void setResultSetQuery(const QXmppResultSetQuery &resultSetQuery);
+ QString node() const;
+ void setNode(const QString &node);
+ QString queryId() const;
+ void setQueryId(const QString &id);
+
+ static bool isMamQueryIq(const QDomElement &element);
+
+protected:
+ void parseElementFromChild(const QDomElement &element);
+ void toXmlElementFromChild(QXmlStreamWriter *writer) const;
+
+private:
+ QXmppDataForm m_form;
+ QXmppResultSetQuery m_resultSetQuery;
+ QString m_node;
+ QString m_queryId;
+};
+
+/// \brief The QXmppMamQueryIq class represents the result IQ for
+/// XEP-0313: Message Archive Management.
+class QXmppMamResultIq : public QXmppIq
+{
+public:
+ QXmppMamResultIq();
+
+ QXmppResultSetReply resultSetReply() const;
+ void setResultSetReply(const QXmppResultSetReply &resultSetReply);
+ bool complete() const;
+ void setComplete(bool complete);
+
+ static bool isMamResultIq(const QDomElement &element);
+
+protected:
+ void parseElementFromChild(const QDomElement &element);
+ void toXmlElementFromChild(QXmlStreamWriter *writer) const;
+
+private:
+ QXmppResultSetReply m_resultSetReply;
+ bool m_complete;
+};
+
+#endif
diff --git a/src/base/base.pri b/src/base/base.pri
index 670de9d6..45a74afb 100644
--- a/src/base/base.pri
+++ b/src/base/base.pri
@@ -13,6 +13,7 @@ INSTALL_HEADERS += \
base/QXmppIq.h \
base/QXmppJingleIq.h \
base/QXmppLogger.h \
+ base/QXmppMamIq.h \
base/QXmppMessage.h \
base/QXmppMucIq.h \
base/QXmppNonSASLAuth.h \
@@ -61,6 +62,7 @@ SOURCES += \
base/QXmppIq.cpp \
base/QXmppJingleIq.cpp \
base/QXmppLogger.cpp \
+ base/QXmppMamIq.cpp \
base/QXmppMessage.cpp \
base/QXmppMucIq.cpp \
base/QXmppNonSASLAuth.cpp \
diff --git a/src/client/QXmppMamManager.cpp b/src/client/QXmppMamManager.cpp
new file mode 100644
index 00000000..8c793144
--- /dev/null
+++ b/src/client/QXmppMamManager.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016-2017 The QXmpp developers
+ *
+ * Author:
+ * Niels Ole Salscheider
+ *
+ * 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 <QDomElement>
+
+#include "QXmppMamManager.h"
+#include "QXmppMamIq.h"
+#include "QXmppClient.h"
+#include "QXmppConstants_p.h"
+#include "QXmppDataForm.h"
+#include "QXmppMessage.h"
+#include "QXmppUtils.h"
+
+/// \cond
+QStringList QXmppMamManager::discoveryFeatures() const
+{
+ // XEP-0313: Message Archive Management
+ return QStringList() << ns_mam;
+}
+
+bool QXmppMamManager::handleStanza(const QDomElement &element)
+{
+ if (element.tagName() == "message") {
+ QDomElement resultElement = element.firstChildElement("result");
+ if (!resultElement.isNull() && resultElement.namespaceURI() == ns_mam) {
+ QDomElement forwardedElement = resultElement.firstChildElement("forwarded");
+ QString queryId = resultElement.attribute("queryid");
+ if (!forwardedElement.isNull() && forwardedElement.namespaceURI() == ns_forwarding) {
+ QDomElement messageElement = forwardedElement.firstChildElement("message");
+ QDomElement delayElement = forwardedElement.firstChildElement("delay");
+ if (!messageElement.isNull()) {
+ QXmppMessage message;
+ message.parse(messageElement);
+ if (!delayElement.isNull() && delayElement.namespaceURI() == ns_delayed_delivery) {
+ const QString stamp = delayElement.attribute("stamp");
+ message.setStamp(QXmppUtils::datetimeFromString(stamp));
+ }
+ emit archivedMessageReceived(queryId, message);
+ }
+ }
+ return true;
+ }
+ } else if (QXmppMamResultIq::isMamResultIq(element)) {
+ QXmppMamResultIq result;
+ result.parse(element);
+ emit resultsRecieved(result.id(), result.resultSetReply(), result.complete());
+ return true;
+ }
+
+ return false;
+}
+/// \endcond
+
+/// Retrieves archived messages. For each received message, the
+/// archiveMessageReceived() signal is emitted. Once all messages are received,
+/// the resultsRecieved() signal is emitted. It returns a result set that can
+/// be used to page through the results.
+/// The number of results may be limited by the server.
+///
+/// \param to Optional entity that should be queried. Leave this empty to query
+/// the local archive.
+/// \param node Optional node that should be queried. This is used when querying
+/// a pubsub node.
+/// \param jid Optional JID to filter the results.
+/// \param start Optional start time to filter the results.
+/// \param end Optional end time to filter the results.
+/// \param resultSetQuery Optional Result Set Management query. This can be used
+/// to limit the number of results and to page through the
+/// archive.
+/// \return query id of the request. This can be used to associate the
+/// corresponding resultsRecieved signal.
+///
+QString QXmppMamManager::retrieveArchivedMessages(const QString &to,
+ const QString &node,
+ const QString &jid,
+ const QDateTime &start,
+ const QDateTime &end,
+ const QXmppResultSetQuery &resultSetQuery)
+{
+ QList<QXmppDataForm::Field> fields;
+
+ QXmppDataForm::Field hiddenField(QXmppDataForm::Field::HiddenField);
+ hiddenField.setKey("FORM_TYPE");
+ hiddenField.setValue(ns_mam);
+ fields << hiddenField;
+
+ if (!jid.isEmpty()) {
+ QXmppDataForm::Field jidField;
+ jidField.setKey("with");
+ jidField.setValue(jid);
+ fields << jidField;
+ }
+
+ if (start.isValid()) {
+ QXmppDataForm::Field startField;
+ startField.setKey("start");
+ startField.setValue(QXmppUtils::datetimeToString(start));
+ fields << startField;
+ }
+
+ if (end.isValid()) {
+ QXmppDataForm::Field endField;
+ endField.setKey("end");
+ endField.setValue(QXmppUtils::datetimeToString(end));
+ fields << endField;
+ }
+
+ QXmppDataForm form;
+ form.setType(QXmppDataForm::Submit);
+ form.setFields(fields);
+
+ QXmppMamQueryIq queryIq;
+ QString queryId = queryIq.id(); /* reuse the IQ id as query id */
+ queryIq.setTo(to);
+ queryIq.setNode(node);
+ queryIq.setQueryId(queryId);
+ queryIq.setForm(form);
+ queryIq.setResultSetQuery(resultSetQuery);
+ client()->sendPacket(queryIq);
+ return queryId;
+}
diff --git a/src/client/QXmppMamManager.h b/src/client/QXmppMamManager.h
new file mode 100644
index 00000000..d2c8e315
--- /dev/null
+++ b/src/client/QXmppMamManager.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016-2017 The QXmpp developers
+ *
+ * Author:
+ * Niels Ole Salscheider
+ *
+ * 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.
+ *
+ */
+
+#ifndef QXMPPMAMMANAGER_H
+#define QXMPPMAMMANAGER_H
+
+#include <QDateTime>
+
+#include "QXmppClientExtension.h"
+#include "QXmppResultSet.h"
+
+class QXmppMessage;
+
+/// \brief The QXmppMamManager class makes it possible to access message
+/// archives as defined by XEP-0313: Message Archive Management.
+///
+/// To make use of this manager, you need to instantiate it and load it into
+/// the QXmppClient instance as follows:
+///
+/// \code
+/// QXmppMamManager *manager = new QXmppMamManager;
+/// client->addExtension(manager);
+/// \endcode
+///
+/// \ingroup Managers
+
+class QXMPP_EXPORT QXmppMamManager : public QXmppClientExtension
+{
+ Q_OBJECT
+
+public:
+ QString retrieveArchivedMessages(const QString &to = QString(),
+ const QString &node = QString(),
+ const QString &jid = QString(),
+ const QDateTime &start = QDateTime(),
+ const QDateTime &end = QDateTime(),
+ const QXmppResultSetQuery &resultSetQuery = QXmppResultSetQuery());
+
+ /// \cond
+ QStringList discoveryFeatures() const;
+ bool handleStanza(const QDomElement &element);
+ /// \endcond
+
+signals:
+ /// This signal is emitted when an archived message is received
+ void archivedMessageReceived(const QString &queryId,
+ const QXmppMessage &message);
+
+ /// This signal is emitted when all results for a request have been received
+ void resultsRecieved(const QString &queryId,
+ const QXmppResultSetReply &resultSetReply,
+ bool complete);
+};
+
+#endif
diff --git a/src/client/client.pri b/src/client/client.pri
index 650300be..bfb3094f 100644
--- a/src/client/client.pri
+++ b/src/client/client.pri
@@ -10,6 +10,7 @@ INSTALL_HEADERS += \
client/QXmppDiscoveryManager.h \
client/QXmppEntityTimeManager.h \
client/QXmppInvokable.h \
+ client/QXmppMamManager.h \
client/QXmppMessageReceiptManager.h \
client/QXmppMucManager.h \
client/QXmppOutgoingClient.h \
@@ -33,6 +34,7 @@ SOURCES += \
client/QXmppConfiguration.cpp \
client/QXmppEntityTimeManager.cpp \
client/QXmppInvokable.cpp \
+ client/QXmppMamManager.cpp \
client/QXmppMessageReceiptManager.cpp \
client/QXmppMucManager.cpp \
client/QXmppOutgoingClient.cpp \