aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2020-04-05 15:46:40 +0200
committerLNJ <lnj@kaidan.im>2020-04-05 16:31:44 +0200
commit92ca98fd87764eda452a063bb06611f79829fd69 (patch)
tree6818626b7da6072b7ebd6a17cca16ec003010089
parentf3aa893f5165feb3020b691434c7ce17119559fd (diff)
downloadqxmpp-92ca98fd87764eda452a063bb06611f79829fd69.tar.gz
QXmppRosterIq: Add 'approved' attribute from RFC6121
The 'approved' attribute was added in RFC6121 to indicate whether a pre-approved subscription exists.
-rw-r--r--src/base/QXmppRosterIq.cpp42
-rw-r--r--src/base/QXmppRosterIq.h2
-rw-r--r--tests/qxmpprosteriq/tst_qxmpprosteriq.cpp57
3 files changed, 92 insertions, 9 deletions
diff --git a/src/base/QXmppRosterIq.cpp b/src/base/QXmppRosterIq.cpp
index 0397c94d..ef06dd0a 100644
--- a/src/base/QXmppRosterIq.cpp
+++ b/src/base/QXmppRosterIq.cpp
@@ -159,24 +159,32 @@ void QXmppRosterIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
class QXmppRosterIq::ItemPrivate : public QSharedData
{
public:
+ ItemPrivate();
+
QString bareJid;
Item::SubscriptionType type;
QString name;
// can be subscribe/unsubscribe (attribute "ask")
QString subscriptionStatus;
QSet<QString> groups;
+ bool approved;
// XEP-0405: Mediated Information eXchange (MIX): Participant Server Requirements
bool isMixChannel = false;
QString mixParticipantId;
};
+QXmppRosterIq::ItemPrivate::ItemPrivate()
+ : type(QXmppRosterIq::Item::NotSet),
+ approved(false)
+{
+}
+
///
/// Constructs a new roster entry.
///
QXmppRosterIq::Item::Item()
: d(new ItemPrivate)
{
- d->type = NotSet;
}
QXmppRosterIq::Item::Item(const QXmppRosterIq::Item &other) = default;
@@ -277,6 +285,7 @@ QXmppRosterIq::Item::subscriptionType() const
return d->type;
}
+
///
/// Sets the subscription type of the roster entry.
///
@@ -287,6 +296,30 @@ void QXmppRosterIq::Item::setSubscriptionType(SubscriptionType type)
d->type = type;
}
+///
+/// Returns whether the item has a pre-approved presence subscription.
+///
+/// \since QXmpp 1.3
+///
+bool QXmppRosterIq::Item::isApproved() const
+{
+ return d->approved;
+}
+
+///
+/// Sets whether the item has a pre-approved presence subscription.
+///
+/// This cannot be used to initiate a pre-approved subscription. For this
+/// purpose the client must send a &lt;presence/&gt; stanza of type
+/// \c subscribed to the user.
+///
+/// \since QXmpp 1.3
+///
+void QXmppRosterIq::Item::setIsApproved(bool approved)
+{
+ d->approved = approved;
+}
+
QString QXmppRosterIq::Item::getSubscriptionTypeStr() const
{
switch (d->type) {
@@ -375,6 +408,11 @@ void QXmppRosterIq::Item::parse(const QDomElement &element)
setSubscriptionTypeFromStr(element.attribute(QStringLiteral("subscription")));
setSubscriptionStatus(element.attribute(QStringLiteral("ask")));
+ // pre-approved
+ const QString approved = element.attribute(QStringLiteral("approved"));
+ d->approved = (approved == QStringLiteral("1") || approved == QStringLiteral("true"));
+
+ // groups
QDomElement groupElement = element.firstChildElement(QStringLiteral("group"));
while (!groupElement.isNull()) {
d->groups << groupElement.text();
@@ -396,6 +434,8 @@ void QXmppRosterIq::Item::toXml(QXmlStreamWriter *writer) const
helperToXmlAddAttribute(writer, QStringLiteral("name"), d->name);
helperToXmlAddAttribute(writer, QStringLiteral("subscription"), getSubscriptionTypeStr());
helperToXmlAddAttribute(writer, QStringLiteral("ask"), subscriptionStatus());
+ if (d->approved)
+ writer->writeAttribute(QStringLiteral("approved"), QStringLiteral("true"));
QSet<QString>::const_iterator i = d->groups.constBegin();
while (i != d->groups.constEnd()) {
diff --git a/src/base/QXmppRosterIq.h b/src/base/QXmppRosterIq.h
index 6567ba62..77e9b522 100644
--- a/src/base/QXmppRosterIq.h
+++ b/src/base/QXmppRosterIq.h
@@ -72,12 +72,14 @@ public:
QString name() const;
QString subscriptionStatus() const;
SubscriptionType subscriptionType() const;
+ bool isApproved() const;
void setBareJid(const QString &);
void setGroups(const QSet<QString> &);
void setName(const QString &);
void setSubscriptionStatus(const QString &);
void setSubscriptionType(SubscriptionType);
+ void setIsApproved(bool);
// XEP-0405: Mediated Information eXchange (MIX): Participant Server Requirements
bool isMixChannel() const;
diff --git a/tests/qxmpprosteriq/tst_qxmpprosteriq.cpp b/tests/qxmpprosteriq/tst_qxmpprosteriq.cpp
index 57839934..f0fb6f34 100644
--- a/tests/qxmpprosteriq/tst_qxmpprosteriq.cpp
+++ b/tests/qxmpprosteriq/tst_qxmpprosteriq.cpp
@@ -33,6 +33,8 @@ class tst_QXmppRosterIq : public QObject
private slots:
void testItem_data();
void testItem();
+ void testApproved_data();
+ void testApproved();
void testVersion_data();
void testVersion();
void testMixAnnotate();
@@ -44,36 +46,44 @@ void tst_QXmppRosterIq::testItem_data()
QTest::addColumn<QByteArray>("xml");
QTest::addColumn<QString>("name");
QTest::addColumn<int>("subscriptionType");
+ QTest::addColumn<bool>("approved");
QTest::newRow("none")
- << QByteArray(R"(<item jid="foo@example.com" subscription="none"/>)")
+ << QByteArray(R"(<item jid="foo@example.com" subscription="none" approved="true"/>)")
<< ""
- << int(QXmppRosterIq::Item::None);
+ << int(QXmppRosterIq::Item::None)
+ << true;
QTest::newRow("from")
<< QByteArray(R"(<item jid="foo@example.com" subscription="from"/>)")
<< ""
- << int(QXmppRosterIq::Item::From);
+ << int(QXmppRosterIq::Item::From)
+ << false;
QTest::newRow("to")
<< QByteArray(R"(<item jid="foo@example.com" subscription="to"/>)")
<< ""
- << int(QXmppRosterIq::Item::To);
+ << int(QXmppRosterIq::Item::To)
+ << false;
QTest::newRow("both")
<< QByteArray(R"(<item jid="foo@example.com" subscription="both"/>)")
<< ""
- << int(QXmppRosterIq::Item::Both);
+ << int(QXmppRosterIq::Item::Both)
+ << false;
QTest::newRow("remove")
<< QByteArray(R"(<item jid="foo@example.com" subscription="remove"/>)")
<< ""
- << int(QXmppRosterIq::Item::Remove);
+ << int(QXmppRosterIq::Item::Remove)
+ << false;
QTest::newRow("notset")
<< QByteArray("<item jid=\"foo@example.com\"/>")
<< ""
- << int(QXmppRosterIq::Item::NotSet);
+ << int(QXmppRosterIq::Item::NotSet)
+ << false;
QTest::newRow("name")
<< QByteArray(R"(<item jid="foo@example.com" name="foo bar"/>)")
<< "foo bar"
- << int(QXmppRosterIq::Item::NotSet);
+ << int(QXmppRosterIq::Item::NotSet)
+ << false;
}
void tst_QXmppRosterIq::testItem()
@@ -81,6 +91,7 @@ void tst_QXmppRosterIq::testItem()
QFETCH(QByteArray, xml);
QFETCH(QString, name);
QFETCH(int, subscriptionType);
+ QFETCH(bool, approved);
QXmppRosterIq::Item item;
parsePacket(item, xml);
@@ -89,7 +100,37 @@ void tst_QXmppRosterIq::testItem()
QCOMPARE(item.name(), name);
QCOMPARE(int(item.subscriptionType()), subscriptionType);
QCOMPARE(item.subscriptionStatus(), QString());
+ QCOMPARE(item.isApproved(), approved);
serializePacket(item, xml);
+
+ item = QXmppRosterIq::Item();
+ item.setBareJid("foo@example.com");
+ item.setName(name);
+ item.setSubscriptionType(QXmppRosterIq::Item::SubscriptionType(subscriptionType));
+ item.setIsApproved(approved);
+ serializePacket(item, xml);
+}
+
+void tst_QXmppRosterIq::testApproved_data()
+{
+ QTest::addColumn<QByteArray>("xml");
+ QTest::addColumn<bool>("approved");
+
+ QTest::newRow("true") << QByteArray(R"(<item jid="foo@example.com" approved="true"/>)") << true;
+ QTest::newRow("1") << QByteArray(R"(<item jid="foo@example.com" approved="1"/>)") << true;
+ QTest::newRow("false") << QByteArray(R"(<item jid="foo@example.com" approved="false"/>)") << false;
+ QTest::newRow("0") << QByteArray(R"(<item jid="foo@example.com" approved="0"/>)") << false;
+ QTest::newRow("empty") << QByteArray(R"(<item jid="foo@example.com"/>)") << false;
+}
+
+void tst_QXmppRosterIq::testApproved()
+{
+ QFETCH(QByteArray, xml);
+ QFETCH(bool, approved);
+
+ QXmppRosterIq::Item item;
+ parsePacket(item, xml);
+ QCOMPARE(item.isApproved(), approved);
}
void tst_QXmppRosterIq::testVersion_data()