Verified Commit ebd9d7bf authored by Linus Jahn's avatar Linus Jahn 🔌 Committed by Linus Jahn
Browse files

Implement HttpUploadHandler and QtHttpUploader and integrate into Kaidan

Closes #125.
parent 36330e99
......@@ -25,8 +25,13 @@ SOURCES += \
src/VCardManager.cpp \
src/XmlLogHandler.cpp \
src/StatusBar.cpp \
src/HttpUploadHandler.cpp \
src/QtHttpUploader.cpp \
src/singleapp/singleapplication.cpp \
src/singleapp/singleapplication_p.cpp
src/singleapp/singleapplication_p.cpp \
src/gloox-extensions/httpuploadmanager.cpp \
src/gloox-extensions/httpuploadrequest.cpp \
src/gloox-extensions/httpuploadslot.cpp
HEADERS += \
src/Database.h \
......@@ -49,8 +54,15 @@ HEADERS += \
src/Globals.h \
src/Enums.h \
src/StatusBar.h \
src/HttpUploadHandler.h \
src/QtHttpUploader.h \
src/singleapp/singleapplication.h \
src/singleapp/singleapplication_p.h
src/singleapp/singleapplication_p.h \
src/gloox-extensions/httpuploadmanager.h \
src/gloox-extensions/httpuploadrequest.h \
src/gloox-extensions/httpuploadslot.h \
src/gloox-extensions/httpuploadhandler.h \
src/gloox-extensions/httpuploader.h
android: INCLUDEPATH += $$PWD/3rdparty/gloox/include
android: LIBS += -L$$PWD/3rdparty/gloox/lib/
......
......@@ -18,9 +18,11 @@ set(KAIDAN_SOURCES
${CURDIR}/PresenceCache.cpp
${CURDIR}/PresenceHandler.cpp
${CURDIR}/ServiceDiscoveryManager.cpp
${CURDIR}/HttpUploadHandler.cpp
${CURDIR}/VCardManager.cpp
${CURDIR}/XmlLogHandler.cpp
${CURDIR}/StatusBar.cpp
${CURDIR}/QtHttpUploader.cpp
# SingleApplication
${CURDIR}/singleapp/singleapplication.cpp
......@@ -28,4 +30,9 @@ set(KAIDAN_SOURCES
# needed to trigger moc generation
${CURDIR}/Enums.h
# kaidan gloox extensions (need to be merged into gloox upstream)
${CURDIR}/gloox-extensions/httpuploadmanager.cpp
${CURDIR}/gloox-extensions/httpuploadrequest.cpp
${CURDIR}/gloox-extensions/httpuploadslot.cpp
)
......@@ -41,6 +41,7 @@
#include "MessageHandler.h"
#include "VCardManager.h"
#include "XmlLogHandler.h"
#include "HttpUploadHandler.h"
#include "Kaidan.h"
// Qt
#include <QDebug>
......@@ -54,6 +55,8 @@
#include <gloox/vcardmanager.h>
#include <gloox/vcardupdate.h>
#include <gloox/delayeddelivery.h>
#include "gloox-extensions/httpuploadrequest.h"
#include "gloox-extensions/httpuploadslot.h"
// package fetch interval in ms
static const unsigned int KAIDAN_CLIENT_LOOP_INTERVAL = 30;
......@@ -118,7 +121,10 @@ void ClientThread::run()
vCardManager = new VCardManager(client, avatarStorage, rosterModel);
rosterManager = new RosterManager(kaidan, client, rosterModel, vCardManager);
presenceHandler = new PresenceHandler(client, presenceCache);
serviceDiscoveryManager = new ServiceDiscoveryManager(client, client->disco());
httpUploadHandler = new HttpUploadHandler(client);
serviceDiscoveryManager = new ServiceDiscoveryManager(
client, client->disco(), httpUploadHandler->getUploadManager()
);
if (enableLogging)
xmlLogHandler = new XmlLogHandler(client);
......@@ -128,6 +134,8 @@ void ClientThread::run()
client->registerStanzaExtension(new gloox::Forward());
client->registerStanzaExtension(new gloox::Carbons());
client->registerStanzaExtension(new gloox::VCardUpdate());
client->registerStanzaExtension(new gloox::HttpUploadRequest());
client->registerStanzaExtension(new gloox::HttpUploadSlot());
// connect slots
connect(this, &ClientThread::sendMessageRequested,
......
......@@ -52,6 +52,7 @@ class MessageModel;
class AvatarFileStorage;
class PresenceCache;
class PresenceHandler;
class HttpUploadHandler;
class ServiceDiscoveryManager;
class VCardManager;
class XmlLogHandler;
......@@ -250,6 +251,7 @@ private:
RosterManager *rosterManager;
MessageSessionHandler *messageSessionHandler;
PresenceCache *presenceCache;
HttpUploadHandler *httpUploadHandler;
PresenceHandler *presenceHandler;
ServiceDiscoveryManager *serviceDiscoveryManager;
VCardManager *vCardManager;
......
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
*/
#include "HttpUploadHandler.h"
#include "QtHttpUploader.h"
#include "gloox-extensions/httpuploadmanager.h"
HttpUploadHandler::HttpUploadHandler(gloox::Client *client, QObject *parent)
: QObject(parent), client(client)
{
manager = new gloox::HttpUploadManager(client);
uploader = new QtHttpUploader(manager);
manager->registerHttpUploadHandler(this);
}
void HttpUploadHandler::handleUploadFailed(int id, gloox::HttpUploadError error,
const std::string &text,
const std::string &stamp)
{
}
void HttpUploadHandler::handleUploadFinished(int id, std::string &getUrl)
{
}
void HttpUploadHandler::handleUploadProcess(int id, long unsigned int sent,
long unsigned int total)
{
}
void HttpUploadHandler::handleUploadServiceRemoved(const gloox::JID &jid)
{
}
void HttpUploadHandler::handleUploadServiceAdded(const gloox::JID &jid,
unsigned long maxFileSize)
{
}
void HttpUploadHandler::handleFileSizeLimitChanged(unsigned long maxFileSize)
{
}
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
*/
#ifndef HTTPUPLOADHANDLER_H
#define HTTPUPLOADHANDLER_H
// gloox
#include "gloox-extensions/httpuploadhandler.h"
#include "gloox-extensions/httpuploadmanager.h"
// Qt
#include <QObject>
namespace gloox {
class Client;
}
class QtHttpUploader;
/**
* @brief Class for handling and starting HTTP File Uploads
*/
class HttpUploadHandler : public QObject, public gloox::HttpUploadHandler
{
Q_OBJECT
public:
/**
* Default constructor
*/
HttpUploadHandler(gloox::Client *client, QObject *parent = nullptr);
gloox::HttpUploadManager* getUploadManager()
{
return manager;
}
protected:
/**
* Called, when a new upload service was added.
*
* @param jid The JID of the upload service that has been added
* @param maxFileSize The maximum file size for uploading to this service
*/
virtual void handleUploadServiceAdded(const gloox::JID &jid,
unsigned long maxFileSize);
/**
* Called, when an upload server has been removed.
*
* @param jid The JID of the upload service that has been removed
*/
virtual void handleUploadServiceRemoved(const gloox::JID &jid);
/**
* Called, when the file size limit has changed.
*
* @param maxFileSize The new maximum file size for uploading
*/
virtual void handleFileSizeLimitChanged(unsigned long maxFileSize);
/**
* Called, when the uploader made progress
*
* @param id Upload job id
* @param sent Number of bytes that has been sent
* @param total Number of total bytes to upload
*/
virtual void handleUploadProcess(int id, unsigned long sent,
unsigned long total);
/**
* Called, when an upload has successfully finished
*
* @param id Upload job id
* @param getUrl HTTPS GET url to share with others and download the file
*/
virtual void handleUploadFinished(int id, std::string &getUrl);
/**
* Called, when an upload job has failed
*
* @param id Upload job id
* @param error The error that has occured
* @param text An optional message about what went wrong
*/
virtual void handleUploadFailed(int id, gloox::HttpUploadError error,
const std::string &text = gloox::EmptyString,
const std::string &stamp = gloox::EmptyString);
private:
gloox::Client *client;
gloox::HttpUploadManager *manager;
QtHttpUploader *uploader;
};
#endif // HTTPUPLOADHANDLER_H
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
*/
#include "QtHttpUploader.h"
#include "gloox-extensions/httpuploadmanager.h"
#include "gloox-extensions/httpuploadslot.h"
// Qt
#include <QFile>
#include <QFileInfo>
#include <QMimeDatabase>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
// Kaidan
#include "Globals.h"
QtHttpUploader::QtHttpUploader(gloox::HttpUploadManager *manager,
QObject *parent)
: QObject(parent), manager(manager)
{
manager->registerHttpUploader(this);
}
QtHttpUploader::~QtHttpUploader()
{
}
bool QtHttpUploader::busy()
{
return runningTasks != 0;
}
void QtHttpUploader::uploadFile(int id, std::string putUrl,
gloox::HeaderFieldMap putHeaders,
std::string localPath)
{
// open file for read
QFile *file = new QFile(QString::fromStdString(localPath));
if (!file->open(QIODevice::ReadOnly)) {
manager->uploadFailed(id, gloox::UploadFileNotFound);
return;
}
// get Content-Type
QMimeDatabase mimeDb;
QString contentType = mimeDb.mimeTypeForFile(QString::fromStdString(
localPath)).name();
// create http put request
QNetworkRequest request(QUrl(QString::fromStdString(putUrl)));
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
for (auto &field : putHeaders) {
request.setRawHeader(field.first.c_str(), field.second.c_str());
}
// send put request and start uploading
QNetworkAccessManager *netMngr = new QNetworkAccessManager();
QNetworkReply *reply = netMngr->put(request, file);
runningTasks++;
// handle finished
connect(reply, &QNetworkReply::finished, [=] () {
runningTasks--;
manager->uploadFinished(id);
});
// error handling
connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
[=] (QNetworkReply::NetworkError code) {
runningTasks--;
manager->uploadFailed(id, gloox::UploadHttpError);
});
// upload progress
connect(reply, &QNetworkReply::uploadProgress, [=] (qint64 sent, qint64 total) {
if (total < 0)
total = 0;
manager->uploadProgress(id, sent, total);
});
// delete everything when finished
connect(reply, &QNetworkReply::finished, file, &QFile::deleteLater);
connect(reply, &QNetworkReply::finished, netMngr, &QNetworkAccessManager::deleteLater);
connect(reply, &QNetworkReply::finished, reply, &QNetworkAccessManager::deleteLater);
}
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
*/
#ifndef QTHTTPUPLOADER_H
#define QTHTTPUPLOADER_H
#include <string.h>
#include "gloox-extensions/httpuploader.h"
#include <QObject>
/**
* @todo write docs
*/
class QtHttpUploader : public QObject, public gloox::HttpUploader
{
Q_OBJECT
public:
/**
* Will register this uploader to the HttpUploadManager
*
* @param manager The HttpUploadManager this uploader will be used with
*/
QtHttpUploader(gloox::HttpUploadManager *manager, QObject *parent = nullptr);
~QtHttpUploader();
/**
* @return True, if currently uploading a file
*/
virtual bool busy();
/**
* It does supports parallel uploads
*/
virtual bool supportsParallel()
{
return true;
}
/**
* @see gloox::HttpUploader::uploadFile
*/
virtual void uploadFile(int id, std::string putUrl,
gloox::HeaderFieldMap putHeaders,
std::string localPath);
private:
gloox::HttpUploadManager *manager;
unsigned int runningTasks = 0;
};
#endif // QTHTTPUPLOADER_H
......@@ -33,6 +33,8 @@
//
#include "ServiceDiscoveryManager.h"
// Std
#include <stdexcept>
// Qt
#include <QString>
#include <QDebug>
......@@ -41,14 +43,16 @@
#include <gloox/client.h>
#include <gloox/disco.h>
#include <gloox/carbons.h>
#include "gloox-extensions/httpuploadmanager.h"
// Kaidan
#include "Globals.h"
ServiceDiscoveryManager::ServiceDiscoveryManager(gloox::Client *client, gloox::Disco *disco)
{
this->disco = disco;
this->client = client;
static const unsigned int DISCO_SERVER_ITEM_INFO = 10001;
ServiceDiscoveryManager::ServiceDiscoveryManager(gloox::Client *client, gloox::Disco *disco,
gloox::HttpUploadManager *httpUploadManager) : client(client), disco(disco),
httpUploadManager(httpUploadManager)
{
// register as disco handler
disco->registerDiscoHandler(this);
// register as connection listener
......@@ -63,8 +67,9 @@ ServiceDiscoveryManager::~ServiceDiscoveryManager()
void ServiceDiscoveryManager::onConnect()
{
// request the disco info from the server
// request disco info & items from the server
disco->getDiscoInfo(gloox::JID(client->server()), std::string(), this, 0);
disco->getDiscoItems(gloox::JID(client->server()), std::string(), this, 0);
}
void ServiceDiscoveryManager::onDisconnect(gloox::ConnectionError error)
......@@ -103,15 +108,39 @@ void ServiceDiscoveryManager::handleDiscoInfo(const gloox::JID& from, const gloo
if (from.bare() == client->server()) {
// XEP-0280: Message Carbons
if (info.hasFeature(gloox::XMLNS_MESSAGE_CARBONS)) {
// send IQ to server to enable message carbons
gloox::IQ iq(gloox::IQ::Set, gloox::JID(), client->getID());
iq.addExtension(new gloox::Carbons(gloox::Carbons::Enable));
client->send(iq);
}
}
if (context == DISCO_SERVER_ITEM_INFO) {
for (gloox::Disco::Identity *identity : info.identities()) {
// check identity for file storage
if (identity->category() == "store" && identity->type() == "file") {
httpUploadManager->tryAddFileStoreService(from, info);
// break out of for loop to not add one service multiple times
break;
}
}
}
}
void ServiceDiscoveryManager::handleDiscoItems(const gloox::JID& from, const gloox::Disco::Items& items, int context)
void ServiceDiscoveryManager::handleDiscoItems(const gloox::JID& from,
const gloox::Disco::Items& items,
int context)
{
if (from.bare() == client->server()) {
// get all disco items of the server and check their disco info
for (gloox::Disco::Item *item : items.items()) {
// don't rerequest info of server
if (item->jid().bare() == client->server())
continue;
disco->getDiscoInfo(item->jid(), std::string(), this, DISCO_SERVER_ITEM_INFO);
}
}
}
bool ServiceDiscoveryManager::handleDiscoSet(const gloox::IQ& iq)
......@@ -120,8 +149,11 @@ bool ServiceDiscoveryManager::handleDiscoSet(const gloox::IQ& iq)
return false;
}
void ServiceDiscoveryManager::handleDiscoError(const gloox::JID &from, const gloox::Error *error, int context)
void ServiceDiscoveryManager::handleDiscoError(const gloox::JID &from,
const gloox::Error *error,
int context)
{
qWarning() << "[ServiceDiscoveryManager] Error occured with"
<< QString::fromStdString(from.full()) << "in context" << context;
qWarning() << "[client] [disco] Error occured with"
<< QString::fromStdString(from.full()) << "in context" << context;
}
......@@ -38,16 +38,17 @@
// gloox
#include <gloox/discohandler.h>
#include <gloox/connectionlistener.h>
namespace gloox {
class Client;
class Disco;
class HttpUploadManager;
}
class ServiceDiscoveryManager : public gloox::DiscoHandler, public gloox::ConnectionListener
{
public:
ServiceDiscoveryManager(gloox::Client *client, gloox::Disco *disco);
ServiceDiscoveryManager(gloox::Client *client, gloox::Disco *disco,
gloox::HttpUploadManager *httpUploadManager);
~ServiceDiscoveryManager();
void setFeaturesAndIdentity();
......@@ -64,6 +65,7 @@ public:
private:
gloox::Client *client;
gloox::Disco *disco;
gloox::HttpUploadManager *httpUploadManager;
};
#endif // SERVICEDISCOVERYMANAGER_H
Markdown is supported
0% or .