aboutsummaryrefslogtreecommitdiff
path: root/src/client/QXmppRosterManager.cpp
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2012-02-08 12:33:41 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2012-02-08 12:33:41 +0000
commit21acd67e9b65bea87902032b12709675905aa922 (patch)
treeed5ae9066b10400c4fe6e67dfaf2f4c37a09c32e /src/client/QXmppRosterManager.cpp
parentcea7ae1e702b82d2d0d0a851de1aae58270b14f6 (diff)
downloadqxmpp-21acd67e9b65bea87902032b12709675905aa922.tar.gz
start moving client-specific code
Diffstat (limited to 'src/client/QXmppRosterManager.cpp')
-rw-r--r--src/client/QXmppRosterManager.cpp421
1 files changed, 421 insertions, 0 deletions
diff --git a/src/client/QXmppRosterManager.cpp b/src/client/QXmppRosterManager.cpp
new file mode 100644
index 00000000..7c2f56ed
--- /dev/null
+++ b/src/client/QXmppRosterManager.cpp
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2008-2011 The QXmpp developers
+ *
+ * Authors:
+ * Manjeet Dahiya
+ * Jeremy Lainé
+ *
+ * Source:
+ * http://code.google.com/p/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 "QXmppClient.h"
+#include "QXmppPresence.h"
+#include "QXmppRosterIq.h"
+#include "QXmppRosterManager.h"
+#include "QXmppUtils.h"
+
+class QXmppRosterManagerPrivate
+{
+public:
+ QXmppRosterManagerPrivate(QXmppRosterManager *qq);
+
+ // map of bareJid and its rosterEntry
+ QMap<QString, QXmppRosterIq::Item> entries;
+
+ // map of resources of the jid and map of resources and presences
+ QMap<QString, QMap<QString, QXmppPresence> > presences;
+
+ // flag to store that the roster has been populated
+ bool isRosterReceived;
+
+ // id of the initial roster request
+ QString rosterReqId;
+
+private:
+ QXmppRosterManager *q;
+};
+
+QXmppRosterManagerPrivate::QXmppRosterManagerPrivate(QXmppRosterManager *qq)
+ : isRosterReceived(false),
+ q(qq)
+{
+}
+
+/// Constructs a roster manager.
+
+QXmppRosterManager::QXmppRosterManager(QXmppClient* client)
+{
+ bool check;
+ Q_UNUSED(check);
+
+ d = new QXmppRosterManagerPrivate(this);
+
+ check = connect(client, SIGNAL(connected()),
+ this, SLOT(_q_connected()));
+ Q_ASSERT(check);
+
+ check = connect(client, SIGNAL(disconnected()),
+ this, SLOT(_q_disconnected()));
+ Q_ASSERT(check);
+
+ check = connect(client, SIGNAL(presenceReceived(QXmppPresence)),
+ this, SLOT(_q_presenceReceived(QXmppPresence)));
+ Q_ASSERT(check);
+}
+
+QXmppRosterManager::~QXmppRosterManager()
+{
+ delete d;
+}
+
+/// Accepts a subscription request.
+///
+/// You can call this method in reply to the subscriptionRequest() signal.
+
+bool QXmppRosterManager::acceptSubscription(const QString &bareJid)
+{
+ QXmppPresence presence;
+ presence.setTo(bareJid);
+ presence.setType(QXmppPresence::Subscribed);
+ return client()->sendPacket(presence);
+}
+
+/// Upon XMPP connection, request the roster.
+///
+void QXmppRosterManager::_q_connected()
+{
+ QXmppRosterIq roster;
+ roster.setType(QXmppIq::Get);
+ roster.setFrom(client()->configuration().jid());
+ d->rosterReqId = roster.id();
+ client()->sendPacket(roster);
+}
+
+void QXmppRosterManager::_q_disconnected()
+{
+ d->entries.clear();
+ d->presences.clear();
+ d->isRosterReceived = false;
+}
+
+bool QXmppRosterManager::handleStanza(const QDomElement &element)
+{
+ if (element.tagName() != "iq" || !QXmppRosterIq::isRosterIq(element))
+ return false;
+
+ // Security check: only server should send this iq
+ // from() should be either empty or bareJid of the user
+ const QString fromJid = element.attribute("from");
+ if (!fromJid.isEmpty() && jidToBareJid(fromJid) != client()->configuration().jidBare())
+ return false;
+
+ QXmppRosterIq rosterIq;
+ rosterIq.parse(element);
+
+ bool isInitial = (d->rosterReqId == rosterIq.id());
+ switch(rosterIq.type())
+ {
+ case QXmppIq::Set:
+ {
+ // send result iq
+ QXmppIq returnIq(QXmppIq::Result);
+ returnIq.setId(rosterIq.id());
+ client()->sendPacket(returnIq);
+
+ // store updated entries and notify changes
+ const QList<QXmppRosterIq::Item> items = rosterIq.items();
+ foreach (const QXmppRosterIq::Item &item, items) {
+ const QString bareJid = item.bareJid();
+ if (item.subscriptionType() == QXmppRosterIq::Item::Remove) {
+ if (d->entries.remove(bareJid)) {
+ // notify the user that the item was removed
+ emit itemRemoved(bareJid);
+ }
+ } else {
+ const bool added = !d->entries.contains(bareJid);
+ d->entries.insert(bareJid, item);
+ if (added) {
+ // notify the user that the item was added
+ emit itemAdded(bareJid);
+ } else {
+ // notify the user that the item changed
+ emit itemChanged(bareJid);
+ }
+
+ // FIXME: remove legacy signal
+ emit rosterChanged(bareJid);
+ }
+ }
+ }
+ break;
+ case QXmppIq::Result:
+ {
+ const QList<QXmppRosterIq::Item> items = rosterIq.items();
+ foreach (const QXmppRosterIq::Item &item, items) {
+ const QString bareJid = item.bareJid();
+ d->entries.insert(bareJid, item);
+ if (!isInitial)
+ emit rosterChanged(bareJid);
+ }
+ if (isInitial)
+ {
+ d->isRosterReceived = true;
+ emit rosterReceived();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void QXmppRosterManager::_q_presenceReceived(const QXmppPresence& presence)
+{
+ const QString jid = presence.from();
+ const QString bareJid = jidToBareJid(jid);
+ const QString resource = jidToResource(jid);
+
+ if (bareJid.isEmpty())
+ return;
+
+ switch(presence.type())
+ {
+ case QXmppPresence::Available:
+ d->presences[bareJid][resource] = presence;
+ emit presenceChanged(bareJid, resource);
+ break;
+ case QXmppPresence::Unavailable:
+ d->presences[bareJid].remove(resource);
+ emit presenceChanged(bareJid, resource);
+ break;
+ case QXmppPresence::Subscribe:
+ if (client()->configuration().autoAcceptSubscriptions())
+ {
+ // accept subscription request
+ acceptSubscription(bareJid);
+
+ // ask for reciprocal subscription
+ subscribe(bareJid);
+ } else {
+ emit subscriptionReceived(bareJid);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/// Refuses a subscription request.
+///
+/// You can call this method in reply to the subscriptionRequest() signal.
+
+bool QXmppRosterManager::refuseSubscription(const QString &bareJid)
+{
+ QXmppPresence presence;
+ presence.setTo(bareJid);
+ presence.setType(QXmppPresence::Unsubscribed);
+ return client()->sendPacket(presence);
+}
+
+/// Adds a new item to the roster without sending any subscription requests.
+///
+/// As a result, the server will initiate a roster push, causing the
+/// itemAdded() or itemChanged() signal to be emitted.
+///
+/// \param bareJid
+/// \param name Optional name for the item.
+/// \param groups Optional groups for the item.
+
+bool QXmppRosterManager::addItem(const QString &bareJid, const QString &name, const QSet<QString> &groups)
+{
+ QXmppRosterIq::Item item;
+ item.setBareJid(bareJid);
+ item.setName(name);
+ item.setGroups(groups);
+ item.setSubscriptionType(QXmppRosterIq::Item::NotSet);
+
+ QXmppRosterIq iq;
+ iq.setType(QXmppIq::Set);
+ iq.addItem(item);
+ return client()->sendPacket(iq);
+}
+
+/// Removes a roster item and cancels subscriptions to and from the contact.
+///
+/// As a result, the server will initiate a roster push, causing the
+/// itemRemoved() signal to be emitted.
+///
+/// \param bareJid
+
+bool QXmppRosterManager::removeItem(const QString &bareJid)
+{
+ QXmppRosterIq::Item item;
+ item.setBareJid(bareJid);
+ item.setSubscriptionType(QXmppRosterIq::Item::Remove);
+
+ QXmppRosterIq iq;
+ iq.setType(QXmppIq::Set);
+ iq.addItem(item);
+ return client()->sendPacket(iq);
+}
+
+/// Renames a roster item.
+///
+/// As a result, the server will initiate a roster push, causing the
+/// itemChanged() signal to be emitted.
+///
+/// \param bareJid
+/// \param name
+
+bool QXmppRosterManager::renameItem(const QString &bareJid, const QString &name)
+{
+ if (!d->entries.contains(bareJid))
+ return false;
+
+ QXmppRosterIq::Item item = d->entries.value(bareJid);
+ item.setName(name);
+
+ QXmppRosterIq iq;
+ iq.setType(QXmppIq::Set);
+ iq.addItem(item);
+ return client()->sendPacket(iq);
+}
+
+/// Requests a subscription to the given contact.
+///
+/// As a result, the server will initiate a roster push, causing the
+/// itemAdded() or itemChanged() signal to be emitted.
+
+bool QXmppRosterManager::subscribe(const QString &bareJid)
+{
+ QXmppPresence packet;
+ packet.setTo(jidToBareJid(bareJid));
+ packet.setType(QXmppPresence::Subscribe);
+ return client()->sendPacket(packet);
+}
+
+/// Removes a subscription to the given contact.
+///
+/// As a result, the server will initiate a roster push, causing the
+/// itemChanged() signal to be emitted.
+
+bool QXmppRosterManager::unsubscribe(const QString &bareJid)
+{
+ QXmppPresence packet;
+ packet.setTo(jidToBareJid(bareJid));
+ packet.setType(QXmppPresence::Unsubscribe);
+ return client()->sendPacket(packet);
+}
+
+/// Function to get all the bareJids present in the roster.
+///
+/// \return QStringList list of all the bareJids
+///
+
+QStringList QXmppRosterManager::getRosterBareJids() const
+{
+ return d->entries.keys();
+}
+
+/// Returns the roster entry of the given bareJid. If the bareJid is not in the
+/// database and empty QXmppRosterIq::Item will be returned.
+///
+/// \param bareJid as a QString
+///
+
+QXmppRosterIq::Item QXmppRosterManager::getRosterEntry(
+ const QString& bareJid) const
+{
+ // will return blank entry if bareJid does'nt exist
+ if(d->entries.contains(bareJid))
+ return d->entries.value(bareJid);
+ else
+ return QXmppRosterIq::Item();
+}
+
+/// Get all the associated resources with the given bareJid.
+///
+/// \param bareJid as a QString
+/// \return list of associated resources as a QStringList
+///
+
+QStringList QXmppRosterManager::getResources(const QString& bareJid) const
+{
+ if(d->presences.contains(bareJid))
+ return d->presences[bareJid].keys();
+ else
+ return QStringList();
+}
+
+/// Get all the presences of all the resources of the given bareJid. A bareJid
+/// can have multiple resources and each resource will have a presence
+/// associated with it.
+///
+/// \param bareJid as a QString
+/// \return Map of resource and its respective presence QMap<QString, QXmppPresence>
+///
+
+QMap<QString, QXmppPresence> QXmppRosterManager::getAllPresencesForBareJid(
+ const QString& bareJid) const
+{
+ if(d->presences.contains(bareJid))
+ return d->presences[bareJid];
+ else
+ return QMap<QString, QXmppPresence>();
+}
+
+/// Get the presence of the given resource of the given bareJid.
+///
+/// \param bareJid as a QString
+/// \param resource as a QString
+/// \return QXmppPresence
+///
+
+QXmppPresence QXmppRosterManager::getPresence(const QString& bareJid,
+ const QString& resource) const
+{
+ if(d->presences.contains(bareJid) && d->presences[bareJid].contains(resource))
+ return d->presences[bareJid][resource];
+ else
+ {
+ QXmppPresence presence;
+ presence.setType(QXmppPresence::Unavailable);
+ presence.setStatus(QXmppPresence::Status::Offline);
+ return presence;
+ }
+}
+
+/// Function to check whether the roster has been received or not.
+///
+/// \return true if roster received else false
+
+bool QXmppRosterManager::isRosterReceived() const
+{
+ return d->isRosterReceived;
+}
+
+// deprecated
+
+void QXmppRosterManager::removeRosterEntry(const QString &bareJid)
+{
+ removeItem(bareJid);
+}
+