diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0ea7822..125d31e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,49 +1,50 @@
# set Kaidans sources (used in main cmake file)
set(KAIDAN_SOURCES
src/main.cpp
src/Kaidan.cpp
src/ClientWorker.cpp
src/AvatarFileStorage.cpp
src/Database.cpp
src/RosterItem.cpp
src/RosterModel.cpp
src/RosterDb.cpp
src/RosterManager.cpp
src/RegistrationManager.cpp
src/Message.cpp
src/MessageModel.cpp
src/MessageDb.cpp
src/MessageHandler.cpp
src/Notifications.cpp
src/PresenceCache.cpp
src/DiscoveryManager.cpp
src/VCardManager.cpp
src/LogHandler.cpp
src/StatusBar.cpp
src/UploadManager.cpp
src/EmojiModel.cpp
src/TransferCache.cpp
src/DownloadManager.cpp
src/QmlUtils.cpp
src/Utils.cpp
# needed to trigger moc generation / to be displayed in IDEs
src/Enums.h
src/Globals.h
# kaidan QXmpp extensions (need to be merged into QXmpp upstream)
src/qxmpp-exts/QXmppHttpUploadIq.cpp
src/qxmpp-exts/QXmppUploadRequestManager.cpp
src/qxmpp-exts/QXmppUploadManager.cpp
src/qxmpp-exts/QXmppColorGenerator.cpp
+ src/qxmpp-exts/QXmppUri.cpp
# hsluv-c required for color generation
src/hsluv-c/hsluv.c
)
if(NOT ANDROID AND NOT IOS)
set(KAIDAN_SOURCES ${KAIDAN_SOURCES}
src/singleapp/singleapplication.cpp
src/singleapp/singleapplication_p.cpp
)
endif()
diff --git a/src/qxmpp-exts/QXmppUri.cpp b/src/qxmpp-exts/QXmppUri.cpp
new file mode 100644
index 0000000..cc5630a
--- /dev/null
+++ b/src/qxmpp-exts/QXmppUri.cpp
@@ -0,0 +1,292 @@
+/*
+ * Kaidan - A user-friendly XMPP client for every device!
+ *
+ * Copyright (C) 2016-2019 Kaidan developers and contributors
+ * (see the LICENSE file for a full list of copyright authors)
+ *
+ * Kaidan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * In addition, as a special exception, the author of Kaidan gives
+ * permission to link the code of its release with the OpenSSL
+ * project's "OpenSSL" library (or with modified versions of it that
+ * use the same license as the "OpenSSL" library), and distribute the
+ * linked executables. You must obey the GNU General Public License in
+ * all respects for all of the code used other than "OpenSSL". If you
+ * modify this file, you may extend this exception to your version of
+ * the file, but you are not obligated to do so. If you do not wish to
+ * do so, delete this exception statement from your version.
+ *
+ * Kaidan 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kaidan. If not, see .
+ */
+
+#include "QXmppUri.h"
+#include
+
+/// actions, e.g. "join" in "group@example.org?join" for joining a groupchat
+
+const QStringList ACTION_STRINGS = QStringList()
+ << ""
+ << "command"
+ << "disco"
+ << "invite"
+ << "join"
+ << "login"
+ << "message"
+ << "pubsub"
+ << "recvfile"
+ << "register"
+ << "remove"
+ << "roster"
+ << "sendfile"
+ << "subscribe"
+ << "unregister"
+ << "unsubscribe"
+ << "vcard";
+
+/// types of a "message" action
+
+const QStringList MESSAGE_TYPE_STRINGS = QStringList()
+ << "error"
+ << "normal"
+ << "chat"
+ << "groupchat"
+ << "headline";
+
+/// keys of a message action's key-value pair
+
+const QStringList MESSAGE_ATTRIBUTES = QStringList()
+ << "subject"
+ << "body"
+ << "thread"
+ << "from"
+ << "id"
+ << "type";
+
+/// Adds a key-value pair to the given pairs if val is not empty.
+/// @param pairs which will be extended by the key-value pair with the given key
+/// @param key key of the given value
+/// @param val value of given key
+
+void helperToAddPair(QList> &pairs, const QString &key,
+ const QString &val)
+{
+ if (!val.isEmpty())
+ pairs << qMakePair(key, val);
+}
+
+/// @return value of a given key in a given query
+/// @param query query to search for the key
+/// @param key to get the corresponding value
+
+QString helperToGetQueryItemValue(const QUrlQuery &query, const QString &key)
+{
+ return query.queryItemValue(key, QUrl::FullyDecoded);
+}
+
+/// Parses the URI from a string.
+/// @param input string which may present an XMPP URI
+
+QXmppUri::QXmppUri(QString input)
+{
+ // We're replacing ';' with '&', so we can reuse the QUrlQuery.
+ QUrl url(input.replace(";", "&"));
+ if (!url.isValid() || url.scheme() != "xmpp")
+ return;
+
+ // set JID
+ setJid(url.path());
+
+ if (!input.contains("?"))
+ return;
+
+ QUrlQuery query(url.query());
+ // check that there are query items (key-value pairs)
+ if (!query.queryItems().size())
+ return;
+
+ m_action = static_cast(
+ ACTION_STRINGS.indexOf(query.queryItems().first().first)
+ );
+
+ switch (m_action) {
+ case Message:
+ m_message.setSubject(helperToGetQueryItemValue(query, "subject"));
+ m_message.setBody(helperToGetQueryItemValue(query, "body"));
+ m_message.setThread(helperToGetQueryItemValue(query, "thread"));
+ m_message.setId(helperToGetQueryItemValue(query, "id"));
+ m_message.setFrom(helperToGetQueryItemValue(query, "from"));
+ if (!helperToGetQueryItemValue(query, "type").isEmpty())
+ m_message.setType(static_cast(
+ MESSAGE_TYPE_STRINGS.indexOf(helperToGetQueryItemValue(query, "type"))
+ ));
+ else
+ m_hasMessageType = false;
+ break;
+ case Login:
+ m_password = helperToGetQueryItemValue(query, "password");
+ break;
+ default:
+ break;
+ }
+}
+
+/// Decodes the URI to a string.
+///
+/// \returns Full XMPP URI
+
+QString QXmppUri::toString()
+{
+ QUrl url;
+ url.setScheme("xmpp");
+ url.setPath(m_jid);
+
+ // Create query items (parameters)
+ QUrlQuery query;
+ QList> queryItems;
+
+ switch (m_action) {
+ case Message:
+ helperToAddPair(queryItems, "body", m_message.body());
+ helperToAddPair(queryItems, "from", m_message.from());
+ helperToAddPair(queryItems, "id", m_message.id());
+ helperToAddPair(queryItems, "thread", m_message.thread());
+ if (m_hasMessageType)
+ helperToAddPair(queryItems, "type", MESSAGE_TYPE_STRINGS.at(
+ int(m_message.type())));
+ helperToAddPair(queryItems, "subject", m_message.subject());
+ break;
+ case Login:
+ helperToAddPair(queryItems, "password", m_password);
+ break;
+ default:
+ break;
+ }
+ query.setQueryItems(queryItems);
+
+ QString output = url.toEncoded();
+ if (m_action != None) {
+ // add action
+ output += "?";
+ output += ACTION_STRINGS.at(int(m_action));
+
+ // add parameters
+ QString queryStr = QUrl::toPercentEncoding(query.toString().replace("&", ";"), ";=");
+ if (!query.isEmpty()) {
+ output += ";";
+ output += queryStr;
+ }
+ }
+
+ return output;
+}
+
+/// Returns the JID this URI is about.
+///
+/// This can also be e.g. a MUC room in case of a Join action.
+
+QString QXmppUri::jid() const
+{
+ return m_jid;
+}
+
+/// Sets the JID this XMPP URI links to.
+///
+/// @param jid JID to be set
+
+void QXmppUri::setJid(const QString &jid)
+{
+ m_jid = jid;
+}
+
+/// Returns the action of this XMPP URI.
+///
+/// This is None in case no action is included.
+
+QXmppUri::Action QXmppUri::action() const
+{
+ return m_action;
+}
+
+/// Sets the action of this XMPP URI, e.g. Join for a URI ending with
+/// \c ?join".
+///
+/// @param action action to be set
+
+void QXmppUri::setAction(const Action &action)
+{
+ m_action = action;
+}
+
+/// Returns true if this XMPP URI has the given action.
+///
+/// @param action action to be checked for
+
+bool QXmppUri::hasAction(const Action &action)
+{
+ return m_action == action;
+}
+
+QString QXmppUri::password() const
+{
+ return m_password;
+}
+
+/// In case the URI has a message query, this can be used to get the attached
+/// message content directly as \c QXmppMessage.
+
+QXmppMessage QXmppUri::message() const
+{
+ return m_message;
+}
+
+/// Sets the attached message for a Message action.
+///
+/// Supported properties are: body, from, id, thread, type, subject.
+/// If you want to include the message type, ensure that \c hasMessageType is
+/// set to true.
+///
+/// @param message message to be set
+
+void QXmppUri::setMessage(const QXmppMessage &message)
+{
+ setAction(Message);
+ m_message = message;
+}
+
+/// Returns true, if the attached message's type is included.
+///
+/// This is required because \c QXmppMessage has no option to set no type.
+
+bool QXmppUri::hasMessageType() const
+{
+ return m_hasMessageType;
+}
+
+/// Sets whether to include the message's type.
+///
+/// This is required because \c QXmppMessage has no option to set an empty type.
+///
+/// @param hasMessageType true if the message's type should be included
+
+void QXmppUri::setHasMessageType(bool hasMessageType)
+{
+ m_hasMessageType = hasMessageType;
+}
+
+/// Checks whether the string starts with the XMPP scheme.
+///
+/// @param uri URI to check for XMPP scheme
+
+bool QXmppUri::isXmppUri(const QString &uri)
+{
+ return uri.startsWith("xmpp:");
+}
diff --git a/src/qxmpp-exts/QXmppUri.h b/src/qxmpp-exts/QXmppUri.h
new file mode 100644
index 0000000..089907a
--- /dev/null
+++ b/src/qxmpp-exts/QXmppUri.h
@@ -0,0 +1,95 @@
+/*
+ * Kaidan - A user-friendly XMPP client for every device!
+ *
+ * Copyright (C) 2016-2019 Kaidan developers and contributors
+ * (see the LICENSE file for a full list of copyright authors)
+ *
+ * Kaidan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * In addition, as a special exception, the author of Kaidan gives
+ * permission to link the code of its release with the OpenSSL
+ * project's "OpenSSL" library (or with modified versions of it that
+ * use the same license as the "OpenSSL" library), and distribute the
+ * linked executables. You must obey the GNU General Public License in
+ * all respects for all of the code used other than "OpenSSL". If you
+ * modify this file, you may extend this exception to your version of
+ * the file, but you are not obligated to do so. If you do not wish to
+ * do so, delete this exception statement from your version.
+ *
+ * Kaidan 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kaidan. If not, see .
+ */
+
+#ifndef QXMPPURI_H
+#define QXMPPURI_H
+
+#include
+
+class QXmppUri
+{
+public:
+ enum Action {
+ None,
+ Command,
+ Disco,
+ Invite,
+ Join,
+ Login,
+ Message,
+ PubSub,
+ RecvFile,
+ Register,
+ Remove,
+ Roster,
+ SendFile,
+ Subscribe,
+ Unregister,
+ Unsubscribe,
+ VCard,
+ };
+
+ QXmppUri() = default;
+ QXmppUri(QString uri);
+
+ QString toString();
+
+ QString jid() const;
+ void setJid(const QString &jid);
+
+ Action action() const;
+ void setAction(const Action &action);
+ bool hasAction(const Action &action);
+
+ // login
+ QString password() const;
+
+ // 'message' query
+ QXmppMessage message() const;
+ void setMessage(const QXmppMessage&);
+
+ bool hasMessageType() const;
+ void setHasMessageType(bool hasMessageType);
+
+ static bool isXmppUri(const QString &uri);
+
+private:
+ QString m_jid;
+ Action m_action = None;
+
+ // login
+ QString m_password;
+
+ // message
+ QXmppMessage m_message;
+ bool m_hasMessageType = false;
+};
+
+#endif // QXMPPURI_H