aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCochise César <cochisecesar@zoho.com>2022-01-10 01:27:06 -0300
committerLinus Jahn <lnj@kaidan.im>2022-03-09 18:29:46 +0100
commitf2aadfefa283aafc88131c643b97acd28989ac20 (patch)
tree2c5bfcf4f3634ba4435151ad1ba51321691d6ae4 /src
parenta69475d8b196605b19e532d62d1fc375630ea8f1 (diff)
downloadqxmpp-f2aadfefa283aafc88131c643b97acd28989ac20.tar.gz
Implement XEP-0080: User Location
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/base/QXmppConstants.cpp3
-rw-r--r--src/base/QXmppConstants_p.h3
-rw-r--r--src/base/QXmppGeolocItem.cpp202
-rw-r--r--src/base/QXmppGeolocItem.h54
-rw-r--r--src/client/QXmppUserLocationManager.cpp96
-rw-r--r--src/client/QXmppUserLocationManager.h39
7 files changed, 401 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5f1e5eb5..2e9d587a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INSTALL_HEADER_FILES
base/QXmppElement.h
base/QXmppEntityTimeIq.h
base/QXmppFutureUtils_p.h
+ base/QXmppGeolocItem.h
base/QXmppHttpUploadIq.h
base/QXmppIbbIq.h
base/QXmppIq.h
@@ -119,6 +120,7 @@ set(INSTALL_HEADER_FILES
client/QXmppTrustStorage.h
client/QXmppUploadRequestManager.h
client/QXmppUserTuneManager.h
+ client/QXmppUserLocationManager.h
client/QXmppVCardManager.h
client/QXmppVersionManager.h
@@ -148,6 +150,7 @@ set(SOURCE_FILES
base/QXmppDiscoveryIq.cpp
base/QXmppElement.cpp
base/QXmppEntityTimeIq.cpp
+ base/QXmppGeolocItem.cpp
base/QXmppHttpUploadIq.cpp
base/QXmppIbbIq.cpp
base/QXmppIq.cpp
@@ -226,6 +229,7 @@ set(SOURCE_FILES
client/QXmppTrustMemoryStorage.cpp
client/QXmppTrustStorage.cpp
client/QXmppUploadRequestManager.cpp
+ client/QXmppUserLocationManager.cpp
client/QXmppUserTuneManager.cpp
client/QXmppVCardManager.cpp
client/QXmppVersionManager.cpp
diff --git a/src/base/QXmppConstants.cpp b/src/base/QXmppConstants.cpp
index d6e46ae6..b738341b 100644
--- a/src/base/QXmppConstants.cpp
+++ b/src/base/QXmppConstants.cpp
@@ -58,6 +58,9 @@ const char *ns_register_feature = "http://jabber.org/features/iq-register";
// XEP-0078: Non-SASL Authentication
const char *ns_auth = "jabber:iq:auth";
const char *ns_authFeature = "http://jabber.org/features/iq-auth";
+// XEP-0080: User Location
+const char *ns_geoloc = "http://jabber.org/protocol/geoloc";
+const char *ns_geoloc_notify = "http://jabber.org/protocol/geoloc+notify";
// XEP-0085: Chat State Notifications
const char *ns_chat_states = "http://jabber.org/protocol/chatstates";
// XEP-0091: Legacy Delayed Delivery
diff --git a/src/base/QXmppConstants_p.h b/src/base/QXmppConstants_p.h
index 7fa7afd5..346c60f5 100644
--- a/src/base/QXmppConstants_p.h
+++ b/src/base/QXmppConstants_p.h
@@ -70,6 +70,9 @@ extern const char *ns_register_feature;
// XEP-0078: Non-SASL Authentication
extern const char *ns_auth;
extern const char *ns_authFeature;
+// XEP-0080: User Location
+extern const char *ns_geoloc;
+extern const char *ns_geoloc_notify;
// XEP-0085: Chat State Notifications
extern const char *ns_chat_states;
// XEP-0091: Legacy Delayed Delivery
diff --git a/src/base/QXmppGeolocItem.cpp b/src/base/QXmppGeolocItem.cpp
new file mode 100644
index 00000000..bef54b69
--- /dev/null
+++ b/src/base/QXmppGeolocItem.cpp
@@ -0,0 +1,202 @@
+// SPDX-FileCopyrightText: 2022 Cochise César <cochisecesar@zoho.com>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "QXmppGeolocItem.h"
+
+#include "QXmppConstants_p.h"
+#include "QXmppUtils.h"
+
+#include <QDomElement>
+#include <QXmlStreamWriter>
+
+/// \cond
+class QXmppGeolocItemPrivate : public QSharedData
+{
+public:
+ std::optional<double> accuracy;
+ QString country;
+ QString locality;
+ std::optional<double> latitude;
+ std::optional<double> longitude;
+};
+/// \endcond
+
+///
+/// \class QXmppGeolocItem
+///
+/// This class represents a PubSub item for \xep{0080, User Location}.
+///
+/// \since QXmpp 1.5
+///
+
+///
+/// Default constructor
+///
+QXmppGeolocItem::QXmppGeolocItem()
+ : d(new QXmppGeolocItemPrivate)
+{
+}
+
+/// Copy-constructor.
+QXmppGeolocItem::QXmppGeolocItem(const QXmppGeolocItem &other) = default;
+
+QXmppGeolocItem::~QXmppGeolocItem() = default;
+
+/// Assignment operator.
+QXmppGeolocItem &QXmppGeolocItem::operator=(const QXmppGeolocItem &other) = default;
+
+///
+/// Returns the horizontal GPS error in meters.
+///
+std::optional<double> QXmppGeolocItem::accuracy() const
+{
+ return d->accuracy;
+}
+
+///
+/// Sets the horizontal GPS error.
+///
+void QXmppGeolocItem::setAccuracy(std::optional<double> accuracy)
+{
+ d->accuracy = std::move(accuracy);
+}
+
+///
+/// Returns the country.
+///
+QString QXmppGeolocItem::country() const
+{
+ return d->country;
+}
+
+///
+/// Sets the country.
+///
+void QXmppGeolocItem::setCountry(QString country)
+{
+ d->country = std::move(country);
+}
+
+///
+/// Returns the latitude in decimal degrees.
+///
+std::optional<double> QXmppGeolocItem::latitude() const
+{
+ return d->latitude;
+}
+
+///
+/// Sets the latitude.
+///
+void QXmppGeolocItem::setLatitude(std::optional<double> lat)
+{
+ if (lat && (*lat > 90 || *lat < -90)) {
+ d->latitude.reset();
+ return;
+ }
+ d->latitude = std::move(lat);
+}
+
+///
+/// Returns the locality such as a town or a city.
+///
+QString QXmppGeolocItem::locality() const
+{
+ return d->locality;
+}
+
+///
+/// Sets the locality.
+///
+void QXmppGeolocItem::setLocality(QString locality)
+{
+ d->locality = std::move(locality);
+}
+
+///
+/// Returns the longitude in decimal degrees.
+///
+std::optional<double> QXmppGeolocItem::longitude() const
+{
+ return d->longitude;
+}
+
+///
+/// Sets the longitude.
+///
+void QXmppGeolocItem::setLongitude(std::optional<double> lon)
+{
+ if (lon && (*lon > 180 || *lon < -180)) {
+ d->longitude.reset();
+ return;
+ }
+ d->longitude = std::move(lon);
+}
+
+///
+/// Returns true, if the element is a valid \xep{0080}: User Location PubSub item.
+///
+bool QXmppGeolocItem::isItem(const QDomElement &itemElement)
+{
+ auto isPayloadValid = [](const QDomElement &payload) -> bool {
+ return payload.tagName() == QStringLiteral("geoloc") &&
+ payload.namespaceURI() == ns_geoloc;
+ };
+
+ return QXmppPubSubItem::isItem(itemElement, isPayloadValid);
+}
+
+/// \cond
+std::optional<double> parseOptDouble(const QDomElement &element)
+{
+ bool ok = false;
+ if (auto val = element.text().toDouble(&ok); ok) {
+ return val;
+ }
+ return {};
+}
+
+void QXmppGeolocItem::parsePayload(const QDomElement &tune)
+{
+ for (auto child = tune.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
+ const auto tagName = child.tagName();
+ if (tagName == QStringLiteral("accuracy")) {
+ d->accuracy = parseOptDouble(child);
+ } else if (tagName == QStringLiteral("country")) {
+ d->country = child.text();
+ } else if (tagName == QStringLiteral("lat")) {
+ setLatitude(parseOptDouble(child));
+ } else if (tagName == QStringLiteral("locality")) {
+ d->locality = child.text();
+ } else if (tagName == QStringLiteral("lon")) {
+ setLongitude(parseOptDouble(child));
+ }
+ }
+}
+
+auto writeTextEl(QXmlStreamWriter *writer, const QString &name, const std::optional<double> &val)
+{
+ if (val.has_value()) {
+ writer->writeTextElement(name, QString::number(*val));
+ }
+}
+auto writeTextEl(QXmlStreamWriter *writer, const QString &name, const QString &val)
+{
+ helperToXmlAddTextElement(writer, name, val);
+}
+
+void QXmppGeolocItem::serializePayload(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement(QStringLiteral("geoloc"));
+ writer->writeDefaultNamespace(ns_geoloc);
+
+ writeTextEl(writer, QStringLiteral("accuracy"), d->accuracy);
+ writeTextEl(writer, QStringLiteral("country"), d->country);
+ writeTextEl(writer, QStringLiteral("lat"), d->latitude);
+ writeTextEl(writer, QStringLiteral("locality"), d->locality);
+ writeTextEl(writer, QStringLiteral("lon"), d->longitude);
+
+ writer->writeEndElement();
+}
+/// \endcond
diff --git a/src/base/QXmppGeolocItem.h b/src/base/QXmppGeolocItem.h
new file mode 100644
index 00000000..5b1148f2
--- /dev/null
+++ b/src/base/QXmppGeolocItem.h
@@ -0,0 +1,54 @@
+// SPDX-FileCopyrightText: 2022 Cochise César <cochisecesar@zoho.com>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#ifndef QXMPPGEOLOCITEM_H
+#define QXMPPGEOLOCITEM_H
+
+#include "QXmppPubSubItem.h"
+
+#include <optional>
+
+#include <QSharedDataPointer>
+
+class QXmppGeolocItemPrivate;
+
+class QXMPP_EXPORT QXmppGeolocItem : public QXmppPubSubItem
+{
+public:
+ QXmppGeolocItem();
+ QXmppGeolocItem(const QXmppGeolocItem &other);
+ ~QXmppGeolocItem();
+
+ QXmppGeolocItem &operator=(const QXmppGeolocItem &other);
+
+ std::optional<double> accuracy() const;
+ void setAccuracy(std::optional<double> accuracy);
+
+ QString country() const;
+ void setCountry(QString country);
+
+ std::optional<double> latitude() const;
+ void setLatitude(std::optional<double> lat);
+
+ QString locality() const;
+ void setLocality(QString locality);
+
+ std::optional<double> longitude() const;
+ void setLongitude(std::optional<double> lon);
+
+ static bool isItem(const QDomElement &itemElement);
+
+protected:
+ /// \cond
+ void parsePayload(const QDomElement &payloadElement) override;
+ void serializePayload(QXmlStreamWriter *writer) const override;
+ /// \endcond
+
+private:
+ QSharedDataPointer<QXmppGeolocItemPrivate> d;
+};
+
+Q_DECLARE_METATYPE(QXmppGeolocItem)
+
+#endif // QXMPPGEOLOCITEM_H
diff --git a/src/client/QXmppUserLocationManager.cpp b/src/client/QXmppUserLocationManager.cpp
new file mode 100644
index 00000000..d85a47d5
--- /dev/null
+++ b/src/client/QXmppUserLocationManager.cpp
@@ -0,0 +1,96 @@
+// SPDX-FileCopyrightText: 2022 Cochise César <cochisecesar@zoho.com>
+// SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "QXmppUserLocationManager.h"
+
+#include "QXmppConstants_p.h"
+#include "QXmppGeolocItem.h"
+#include "QXmppPep_p.h"
+
+using namespace QXmpp::Private;
+
+///
+/// \class QXmppUserLocationManager
+///
+/// The QXmppUserLocationManager implements \xep{0080, User Location}. You'll receive
+/// location updates from all presence subscriptions. You can publish location
+/// information on the user's account (publish()) and request location information
+/// from specific accounts (request()).
+///
+/// The manager needs to be added to the client first and also requires the
+/// QXmppPubSubManager.
+/// \code
+/// QXmppClient client;
+/// auto *pubSubManager = client.addNewExtension<QXmppPubSubManager>();
+/// auto *locationManager = client.addNewExtension<QXmppUserLocationManager>();
+/// \endcode
+///
+/// \since QXmpp 1.5
+///
+/// \ingroup Managers
+///
+
+///
+/// \typedef QXmppUserLocationManager::Item
+///
+/// Used pubsub item type.
+///
+
+///
+/// \typedef QXmppUserLocationManager::GetResult
+///
+/// Contains the User Location information or an error.
+///
+
+///
+/// \typedef QXmppUserLocationManager::PublishResult
+///
+/// Contains the ID of the published item on success or a stanza error.
+///
+
+///
+/// \fn QXmppUserLocationManager::itemReceived()
+///
+/// Emitted whenever a \xep{0080, User Location} items event arrives.
+///
+
+QXmppUserLocationManager::QXmppUserLocationManager() = default;
+
+QStringList QXmppUserLocationManager::discoveryFeatures() const
+{
+ return {
+ ns_geoloc,
+ ns_geoloc_notify,
+ };
+}
+
+///
+/// Request User Location information from an account.
+///
+/// \param jid The account JID to request.
+///
+auto QXmppUserLocationManager::request(const QString &jid)
+ -> QFuture<GetResult>
+{
+ return Pep::request<Item>(pubSub(), jid, ns_geoloc, this);
+}
+
+///
+/// Publishes User Location information on the user's account.
+///
+/// \param item The User Location item to be published.
+///
+auto QXmppUserLocationManager::publish(const QXmppGeolocItem &item)
+ -> QFuture<PublishResult>
+{
+ return pubSub()->publishPepItem(ns_geoloc, item);
+}
+
+/// \cond
+bool QXmppUserLocationManager::handlePubSubEvent(const QDomElement &element, const QString &pubSubService, const QString &nodeName)
+{
+ return Pep::handlePubSubEvent<Item>(element, pubSubService, nodeName, ns_geoloc, this, &QXmppUserLocationManager::itemReceived);
+}
+/// \endcond
diff --git a/src/client/QXmppUserLocationManager.h b/src/client/QXmppUserLocationManager.h
new file mode 100644
index 00000000..9033d512
--- /dev/null
+++ b/src/client/QXmppUserLocationManager.h
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
+// SPDX-FileCopyrightText: 2022 Cochise César <cochisecesar@zoho.com>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#ifndef QXMPPUSERLOCATIONMANAGER_H
+#define QXMPPUSERLOCATIONMANAGER_H
+
+#include "QXmppPubSubEventManager.h"
+
+#include <variant>
+
+class QXmppGeolocItem;
+
+class QXMPP_EXPORT QXmppUserLocationManager : public QXmppPubSubEventManager
+{
+ Q_OBJECT
+
+public:
+ using Item = QXmppGeolocItem;
+ using GetResult = std::variant<Item, QXmppStanza::Error>;
+ using PublishResult = std::variant<QString, QXmppStanza::Error>;
+
+ QXmppUserLocationManager();
+
+ QStringList discoveryFeatures() const override;
+
+ QFuture<GetResult> request(const QString &jid);
+ QFuture<PublishResult> publish(const Item &);
+
+ Q_SIGNAL void itemReceived(const QString &jid, const QXmppGeolocItem &);
+
+protected:
+ /// \cond
+ bool handlePubSubEvent(const QDomElement &element, const QString &pubSubService, const QString &nodeName) override;
+ /// \endcond
+};
+
+#endif // QXMPPUSERLOCATIONMANAGER_H