diff options
| author | Linus Jahn <lnj@kaidan.im> | 2019-01-04 20:49:09 +0100 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2019-05-04 10:31:43 +0200 |
| commit | 537e325e2d44e696993b78ae2b8dd8437433c2b9 (patch) | |
| tree | bc4604c1d0894764d25e9237942cd1f13a0cdd17 | |
| parent | 754cc5a70479a54659dbc93ccb5bf28e1da77ef4 (diff) | |
| download | qxmpp-537e325e2d44e696993b78ae2b8dd8437433c2b9.tar.gz | |
Implement MIX-CORE XEP-0369: Info/Participant node items
This implements the pubsub items for the MIX participants and info node
as defined by XEP-0369: Mediated Information eXchange (MIX) in version
0.14.2.
https://xmpp.org/extensions/xep-0369.html#participants-node
https://xmpp.org/extensions/xep-0369.html#info-node
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/base/QXmppMixItem.cpp | 226 | ||||
| -rw-r--r-- | src/base/QXmppMixItem.h | 87 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tests/qxmppmixitem/tst_qxmppmixitem.cpp | 159 |
5 files changed, 475 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2e48bffa..d8eda94d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,7 @@ set(INSTALL_HEADER_FILES base/QXmppMamIq.h base/QXmppMessage.h base/QXmppMixIq.h + base/QXmppMixItem.h base/QXmppMucIq.h base/QXmppNonSASLAuth.h base/QXmppPingIq.h @@ -101,6 +102,7 @@ set(SOURCE_FILES base/QXmppMamIq.cpp base/QXmppMessage.cpp base/QXmppMixIq.cpp + base/QXmppMixItem.cpp base/QXmppMucIq.cpp base/QXmppNonSASLAuth.cpp base/QXmppPingIq.cpp diff --git a/src/base/QXmppMixItem.cpp b/src/base/QXmppMixItem.cpp new file mode 100644 index 00000000..5b1d7c00 --- /dev/null +++ b/src/base/QXmppMixItem.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Author: + * Linus Jahn <lnj@kaidan.im> + * + * 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 "QXmppMixItem.h" +#include "QXmppDataForm.h" +#include "QXmppConstants_p.h" +#include "QXmppUtils.h" +#include <QDomElement> +#include <QBuffer> + +class QXmppMixInfoItemPrivate : QSharedData +{ +public: + QString name; + QString description; + QStringList contactJids; +}; + +QXmppMixInfoItem::QXmppMixInfoItem() + : d(new QXmppMixInfoItemPrivate) +{ +} + +/// Returns the user-specified name of the MIX channel. This is not the name +/// part of the channel's JID. + +QString QXmppMixInfoItem::name() const +{ + return d->name; +} + +/// Sets the name of the channel. + +void QXmppMixInfoItem::setName(const QString& name) +{ + d->name = name; +} + +/// Returns the description of the channel. This string might be very long. + +QString QXmppMixInfoItem::description() const +{ + return d->description; +} + +/// Sets the longer channel description. + +void QXmppMixInfoItem::setDescription(const QString& description) +{ + d->description = description; +} + +/// Returns a list of JIDs that are responsible for this channel. + +QStringList QXmppMixInfoItem::contactJids() const +{ + return d->contactJids; +} + +/// Sets a list of public JIDs that are responsible for this channel. + +void QXmppMixInfoItem::setContactJids(const QStringList& contactJids) +{ + d->contactJids = contactJids; +} + +/// Returns true, if the given dom element is a MIX channel info item. + +bool QXmppMixInfoItem::isMixChannelInfo(const QDomElement& element) +{ + QXmppDataForm form; + form.parse(element); + for (const auto &field : form.fields()) { + if (field.key() == "FORM_TYPE") + return field.value() == ns_mix; + } + return false; +} + +void QXmppMixInfoItem::parse(const QXmppElement& element) +{ + QXmppDataForm form; + form.parse(element.sourceDomElement()); + + for (auto& field : form.fields()) { + if (field.key() == "Name") + d->name = field.value().toString(); + else if (field.key() == "Description") + d->description = field.value().toString(); + else if (field.key() == "Contact") + d->contactJids = field.value().toStringList(); + } +} + +QXmppElement QXmppMixInfoItem::toElement() const +{ + QXmppDataForm form; + form.setType(QXmppDataForm::Result); + QList<QXmppDataForm::Field> fields; + + QXmppDataForm::Field formType; + formType.setType(QXmppDataForm::Field::HiddenField); + formType.setKey("FORM_TYPE"); + formType.setValue(ns_mix); + fields << formType; + + QXmppDataForm::Field nameField; + nameField.setKey("Name"); + nameField.setValue(d->name); + fields << nameField; + + QXmppDataForm::Field descriptionField; + descriptionField.setKey("Description"); + descriptionField.setValue(d->description); + fields << descriptionField; + + QXmppDataForm::Field contactsField; + contactsField.setKey("Contact"); + contactsField.setValue(d->contactJids); + contactsField.setType(QXmppDataForm::Field::JidMultiField); + fields << contactsField; + + form.setFields(fields); + + // FIXME: this is too complicated; maybe don't use QXmppElement in QXmppPubSubItem? + QBuffer buffer; + buffer.open(QIODevice::ReadWrite); + QXmlStreamWriter writer(&buffer); + form.toXml(&writer); + + QDomDocument doc; + doc.setContent(buffer.data()); + return QXmppElement(doc.documentElement()); +} + +class QXmppMixParticipantItemPrivate : QSharedData +{ +public: + QString nick; + QString jid; +}; + +QXmppMixParticipantItem::QXmppMixParticipantItem() + : d(new QXmppMixParticipantItemPrivate) +{ +} + +/// Returns the participant's nickname. + +QString QXmppMixParticipantItem::nick() const +{ + return d->nick; +} + +/// Sets the participants nickname. + +void QXmppMixParticipantItem::setNick(const QString& nick) +{ + d->nick = nick; +} + +/// Returns the participant's JID. + +QString QXmppMixParticipantItem::jid() const +{ + return d->jid; +} + +/// Sets the participant's JID. + +void QXmppMixParticipantItem::setJid(const QString& jid) +{ + d->jid = jid; +} + +void QXmppMixParticipantItem::parse(const QXmppElement& itemContent) +{ + d->nick = itemContent.firstChildElement("nick").value(); + d->jid = itemContent.firstChildElement("jid").value(); +} + +QXmppElement QXmppMixParticipantItem::toElement() const +{ + QXmppElement element; + element.setTagName("participant"); + element.setAttribute("xmlns", ns_mix); + + QXmppElement jid; + jid.setTagName("jid"); + jid.setValue(d->jid); + element.appendChild(jid); + + QXmppElement nick; + nick.setTagName("nick"); + nick.setValue(d->nick); + element.appendChild(nick); + + return element; +} + +/// Returns true, if this dom element is a MIX participant item. + +bool QXmppMixParticipantItem::isMixParticipantItem(const QDomElement &element) +{ + return element.tagName() == "participant" && element.namespaceURI() == ns_mix; +} diff --git a/src/base/QXmppMixItem.h b/src/base/QXmppMixItem.h new file mode 100644 index 00000000..d4f046c1 --- /dev/null +++ b/src/base/QXmppMixItem.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Author: + * Linus Jahn <lnj@kaidan.im> + * + * 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 QXMPPMIXITEM_H +#define QXMPPMIXITEM_H + +#include "QXmppElement.h" + +class QXmppMixInfoItemPrivate; +class QXmppMixParticipantItemPrivate; + +/// \brief The QXmppMixInfoItem class represents a PubSub item of a MIX +/// channel containing channel information as defined by XEP-0369: Mediated +/// Information eXchange (MIX). +/// +/// \ingroup Stanzas + +class QXMPP_EXPORT QXmppMixInfoItem +{ +public: + QXmppMixInfoItem(); + + QString name() const; + void setName(const QString&); + + QString description() const; + void setDescription(const QString&); + + QStringList contactJids() const; + void setContactJids(const QStringList&); + + void parse(const QXmppElement& itemContent); + QXmppElement toElement() const; + + static bool isMixChannelInfo(const QDomElement&); + +private: + QXmppMixInfoItemPrivate *d; +}; + +/// \brief The QXmppMixParticipantItem class represents a PubSub item of a MIX +/// channel participant as defined by XEP-0369: Mediated Information eXchange +/// (MIX). +/// +/// \ingroup Stanzas + +class QXMPP_EXPORT QXmppMixParticipantItem +{ +public: + QXmppMixParticipantItem(); + + QString nick() const; + void setNick(const QString&); + + QString jid() const; + void setJid(const QString&); + + void parse(const QXmppElement& itemContent); + QXmppElement toElement() const; + + static bool isMixParticipantItem(const QDomElement&); + +private: + QXmppMixParticipantItemPrivate *d; +}; + +#endif // QXMPPMIXITEM_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 223a198c..794cd609 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -25,6 +25,7 @@ add_simple_test(qxmppiceconnection) add_simple_test(qxmppiq) add_simple_test(qxmppjingleiq) add_simple_test(qxmppmammanager) +add_simple_test(qxmppmixitem) add_simple_test(qxmppmessage) add_simple_test(qxmppmixiq) add_simple_test(qxmppnonsaslauthiq) diff --git a/tests/qxmppmixitem/tst_qxmppmixitem.cpp b/tests/qxmppmixitem/tst_qxmppmixitem.cpp new file mode 100644 index 00000000..46e3e680 --- /dev/null +++ b/tests/qxmppmixitem/tst_qxmppmixitem.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Author: + * Linus Jahn <lnj@kaidan.im> + * + * 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 <QDomDocument> +#include "QXmppMixItem.h" +#include "QXmppPubSubIq.h" +#include "util.h" + +class tst_QXmppMixItem : public QObject +{ + Q_OBJECT + +private slots: + void testInfo(); + void testIsInfoItem(); + void testParticipant(); + void testIsParticipantItem(); +}; + +void tst_QXmppMixItem::testInfo() +{ + const QByteArray xml( + "<x xmlns=\"jabber:x:data\" type=\"result\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>urn:xmpp:mix:core:0</value>" + "</field>" + "<field type=\"text-single\" var=\"Name\">" + "<value>Witches Coven</value>" + "</field>" + "<field type=\"text-single\" var=\"Description\">" + "<value>A location not far from the blasted heath where the " + "three witches meet</value>" + "</field>" + "<field type=\"jid-multi\" var=\"Contact\">" + "<value>greymalkin@shakespeare.example</value>" + "<value>joan@shakespeare.example</value>" + "</field>" + "</x>" + ); + + QXmppMixInfoItem item; + parsePacket(item, xml); + + QCOMPARE(item.name(), QString("Witches Coven")); + QCOMPARE(item.description(), QString("A location not far from the blasted " + "heath where the three witches meet")); + QCOMPARE(item.contactJids(), QStringList() << "greymalkin@shakespeare.example" + << "joan@shakespeare.example"); + + QXmppElement element = item.toElement(); + serializePacket(element, xml); + + // test setters + item.setName("Skynet Development"); + QCOMPARE(item.name(), QString("Skynet Development")); + item.setDescription("Very cool development group."); + QCOMPARE(item.description(), QString("Very cool development group.")); + item.setContactJids(QStringList() << "somebody@example.org"); + QCOMPARE(item.contactJids(), QStringList() << "somebody@example.org"); +} + +void tst_QXmppMixItem::testIsInfoItem() +{ + QDomDocument doc; + QDomElement element; + + const QByteArray xmlCorrect( + "<x xmlns=\"jabber:x:data\" type=\"result\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>urn:xmpp:mix:core:0</value>" + "</field>" + "</x>" + ); + QCOMPARE(doc.setContent(xmlCorrect, true), true); + element = doc.documentElement(); + QVERIFY(QXmppMixInfoItem::isMixChannelInfo(element)); + + const QByteArray xmlWrong( + "<x xmlns=\"jabber:x:data\" type=\"result\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>other:namespace</value>" + "</field>" + "</x>" + ); + QCOMPARE(doc.setContent(xmlWrong, true), true); + element = doc.documentElement(); + QVERIFY(!QXmppMixInfoItem::isMixChannelInfo(element)); +} + +void tst_QXmppMixItem::testParticipant() +{ + const QByteArray xml( + "<participant xmlns=\"urn:xmpp:mix:core:0\">" + "<jid>hag66@shakespeare.example</jid>" + "<nick>thirdwitch</nick>" + "</participant>" + ); + + QXmppMixParticipantItem item; + parsePacket(item, xml); + + QCOMPARE(item.nick(), QString("thirdwitch")); + QCOMPARE(item.jid(), QString("hag66@shakespeare.example")); + + QXmppElement element = item.toElement(); + serializePacket(element, xml); + + // test setters + item.setNick("thomasd"); + QCOMPARE(item.nick(), QString("thomasd")); + item.setJid("thomas@d.example"); + QCOMPARE(item.jid(), QString("thomas@d.example")); +} + +void tst_QXmppMixItem::testIsParticipantItem() +{ + QDomDocument doc; + QDomElement element; + + const QByteArray xmlCorrect( + "<participant xmlns=\"urn:xmpp:mix:core:0\">" + "</participant>" + ); + QCOMPARE(doc.setContent(xmlCorrect, true), true); + element = doc.documentElement(); + QVERIFY(QXmppMixParticipantItem::isMixParticipantItem(element)); + + const QByteArray xmlWrong( + "<participant xmlns=\"other:namespace:1\">" + "</participant>" + ); + QCOMPARE(doc.setContent(xmlWrong, true), true); + element = doc.documentElement(); + QVERIFY(!QXmppMixParticipantItem::isMixParticipantItem(element)); +} + +QTEST_MAIN(tst_QXmppMixItem) +#include "tst_qxmppmixitem.moc" |
