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

Make file uploading functional (still missing messaging integration)

This will make the attachment button functional. When the button is pressed the
selected file will be uploaded via. HTTP File Upload. The download link can only
be get by copying it from the XML log. The link won't be sent into a message nor
into a SIMS element.

Also the HttpUploadHandler has been renamed to UploadHandler, because it should
handle general file uploading, not limited to HTTP File Upload. Probably also
jingle sessions for SIMS will be created in there, later.
parent d4ddcf4b
......@@ -25,7 +25,7 @@ SOURCES += \
src/VCardManager.cpp \
src/XmlLogHandler.cpp \
src/StatusBar.cpp \
src/HttpUploadHandler.cpp \
src/UploadHandler.cpp \
src/QtHttpUploader.cpp \
src/singleapp/singleapplication.cpp \
src/singleapp/singleapplication_p.cpp \
......@@ -63,7 +63,7 @@ HEADERS += \
src/Globals.h \
src/Enums.h \
src/StatusBar.h \
src/HttpUploadHandler.h \
src/UploadHandler.h \
src/QtHttpUploader.h \
src/singleapp/singleapplication.h \
src/singleapp/singleapplication_p.h \
......
......@@ -18,7 +18,7 @@ set(KAIDAN_SOURCES
${CURDIR}/PresenceCache.cpp
${CURDIR}/PresenceHandler.cpp
${CURDIR}/ServiceDiscoveryManager.cpp
${CURDIR}/HttpUploadHandler.cpp
${CURDIR}/UploadHandler.cpp
${CURDIR}/VCardManager.cpp
${CURDIR}/XmlLogHandler.cpp
${CURDIR}/StatusBar.cpp
......
......@@ -41,7 +41,7 @@
#include "MessageHandler.h"
#include "VCardManager.h"
#include "XmlLogHandler.h"
#include "HttpUploadHandler.h"
#include "UploadHandler.h"
#include "Kaidan.h"
// Qt
#include <QDebug>
......@@ -121,9 +121,9 @@ void ClientThread::run()
vCardManager = new VCardManager(client, avatarStorage, rosterModel);
rosterManager = new RosterManager(kaidan, client, rosterModel, vCardManager);
presenceHandler = new PresenceHandler(client, presenceCache);
httpUploadHandler = new HttpUploadHandler(client);
uploadHandler = new UploadHandler(client);
serviceDiscoveryManager = new ServiceDiscoveryManager(
client, client->disco(), httpUploadHandler->getUploadManager()
client, client->disco(), uploadHandler->getUploadManager()
);
if (enableLogging)
xmlLogHandler = new XmlLogHandler(client);
......@@ -142,6 +142,8 @@ void ClientThread::run()
messageSessionHandler->getMessageHandler(), &MessageHandler::sendMessage);
connect(this, &ClientThread::chatPartnerChanged,
messageSessionHandler->getMessageHandler(), &MessageHandler::setChatPartner);
connect(this, &ClientThread::sendFileRequested,
uploadHandler, &UploadHandler::uploadFile);
connect(this, &ClientThread::addContactRequested,
rosterManager, &RosterManager::addContact);
connect(this, &ClientThread::removeContactRequested,
......
......@@ -52,7 +52,7 @@ class MessageModel;
class AvatarFileStorage;
class PresenceCache;
class PresenceHandler;
class HttpUploadHandler;
class UploadHandler;
class ServiceDiscoveryManager;
class VCardManager;
class XmlLogHandler;
......@@ -165,27 +165,32 @@ signals:
* Emitted when the connection state has changed.
*/
void connectionStateChanged(ConnectionState state);
/**
* Emitted when the client failed to connect giving the reason of it.
*/
void disconnReasonChanged(DisconnReason reason);
/**
* Emit to start connecting on the client's thread.
*/
void connectRequested();
/**
* Emit to start the disconnection on the client's thread.
*/
void disconnectRequested();
/**
* Emit to send a message to a chat partner.
*/
void sendMessageRequested(QString toJid, QString message);
/**
* Emit to start uploading and sending a file
*/
void sendFileRequested(QString jid, QString filePath);
/**
* Emit to add a new contact to the roster.
*/
......@@ -250,9 +255,9 @@ private:
ClientWorker *worker;
RosterManager *rosterManager;
MessageSessionHandler *messageSessionHandler;
PresenceCache *presenceCache;
HttpUploadHandler *httpUploadHandler;
PresenceHandler *presenceHandler;
PresenceCache *presenceCache;
UploadHandler *uploadHandler;
ServiceDiscoveryManager *serviceDiscoveryManager;
VCardManager *vCardManager;
XmlLogHandler *xmlLogHandler;
......
......@@ -213,6 +213,18 @@ void Kaidan::sendMessage(QString jid, QString message)
}
}
void Kaidan::sendFile(QString jid, QString filePath)
{
if (client->isConnected()) {
// convert file-URLs to file paths
filePath.replace("file://", "");
emit client->sendFileRequested(jid, filePath);
} else {
emit passiveNotificationRequested(tr("Could not send file, as a result of not being connected."));
qWarning() << "[main] Could not send file, as a result of not being connected.";
}
}
void Kaidan::addContact(QString jid, QString nick, QString msg)
{
if (client->isConnected()) {
......
......@@ -121,6 +121,11 @@ public:
*/
Q_INVOKABLE void sendMessage(QString jid, QString message);
/**
* Upload and send file
*/
Q_INVOKABLE void sendFile(QString jid, QString filePath);
/**
* Add a contact to your roster
*
......
......@@ -59,7 +59,7 @@ bool QtHttpUploader::busy()
void QtHttpUploader::uploadFile(int id, std::string putUrl,
gloox::HeaderFieldMap putHeaders,
std::string localPath)
std::string &localPath, std::string &contentType)
{
// open file for read
QFile *file = new QFile(QString::fromStdString(localPath));
......@@ -69,13 +69,16 @@ void QtHttpUploader::uploadFile(int id, std::string putUrl,
}
// get Content-Type
QMimeDatabase mimeDb;
QString contentType = mimeDb.mimeTypeForFile(QString::fromStdString(
localPath)).name();
if (contentType.empty()) {
QMimeDatabase mimeDb;
contentType = mimeDb.mimeTypeForFile(QString::fromStdString(
localPath)).name().toStdString();
}
// create http put request
QNetworkRequest request(QUrl(QString::fromStdString(putUrl)));
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
request.setHeader(QNetworkRequest::ContentTypeHeader,
QString::fromStdString(contentType));
for (auto &field : putHeaders) {
request.setRawHeader(field.first.c_str(), field.second.c_str());
}
......
......@@ -70,7 +70,7 @@ public:
*/
virtual void uploadFile(int id, std::string putUrl,
gloox::HeaderFieldMap putHeaders,
std::string localPath);
std::string &localPath, std::string &contentType);
private:
gloox::HttpUploadManager *manager;
......
/*
* 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 "UploadHandler.h"
#include "QtHttpUploader.h"
// gloox
#include "gloox-extensions/httpuploadmanager.h"
#include "gloox-extensions/reference.h"
#include "gloox-extensions/sims.h"
#include "gloox-extensions/processinghints.h"
#include "gloox-extensions/jinglefile.h"
#include "gloox-extensions/hash.h"
// Qt
#include <QMimeDatabase>
#include <QDebug>
UploadHandler::UploadHandler(gloox::Client *client, QObject *parent)
: QObject(parent), client(client)
{
manager = new gloox::HttpUploadManager(client);
uploader = new QtHttpUploader(manager);
manager->registerHttpUploadHandler(this);
}
void UploadHandler::uploadFile(QString jid, QString filePath)
{
// get MIME-type
QMimeDatabase mimeDb;
QString contentType = mimeDb.mimeTypeForFile(filePath).name();
int id = manager->uploadFile(filePath.toStdString(), true,
contentType.toStdString());
}
void UploadHandler::handleUploadFailed(int id, gloox::HttpUploadError error,
const std::string &text,
const std::string &stamp)
{
qDebug() << "[client] A file upload has failed.";
}
void UploadHandler::handleUploadFinished(int id, std::string &name,
std::string &getUrl,
std::string &contentType,
unsigned long &size)
{
qDebug() << "[client] A file upload has finished.";
// TODO: send SIMS message (and optionally also create jingle object)
}
void UploadHandler::handleUploadProcess(int id, long unsigned int sent,
long unsigned int total)
{
}
void UploadHandler::handleUploadServiceRemoved(const gloox::JID &jid)
{
}
void UploadHandler::handleUploadServiceAdded(const gloox::JID &jid,
unsigned long maxFileSize)
{
}
void UploadHandler::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 UPLOADHANDLER_H
#define UPLOADHANDLER_H
// gloox
#include "gloox-extensions/httpuploadhandler.h"
#include "gloox-extensions/httpuploadmanager.h"
// Qt
#include <QObject>
#include <QMap>
namespace gloox {
class Client;
}
class QtHttpUploader;
/**
* @class UploadHandler Class for handling and starting HTTP File Uploads
*/
class UploadHandler : public QObject, public gloox::HttpUploadHandler
{
Q_OBJECT
public:
/**
* Default constructor
*/
UploadHandler(gloox::Client *client, QObject *parent = nullptr);
gloox::HttpUploadManager* getUploadManager()
{
return manager;
}
public slots:
/**
* Starts uploading a file
*
* @todo also add entry to database
*/
void uploadFile(QString jid, QString filePath);
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 &name,
std::string &getUrl, std::string &contentType,
unsigned long &size);
/**
* 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;
QMap<int, std::string> filePaths;
};
#endif // UPLOADHANDLER_H
......@@ -30,7 +30,7 @@
import QtQuick 2.6
import QtQuick.Controls 2.0 as Controls
import QtQuick.Dialogs 1.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.2 as Kirigami
import QtGraphicalEffects 1.0
......@@ -47,15 +47,20 @@ Kirigami.ScrollablePage {
FileDialog {
id: fileDialog
title: "Please choose a file to upload"
title: qsTr("Please choose a file to upload")
folder: shortcuts.home
nameFilters: [ "Image files (*.jpg *.png)", "Videos (*.mp4 *.mkv *.avi *.webm)", "Audio Files (*.mp3 *.wav *.flac *.ogg *.m4a *.mka)", "Documents (*.doc *.docx *.odt)", "All files (*)" ]
selectMultiple: true
nameFilters: [
"Images (*.jpg *.jpeg *.png *.gif)",
"Videos (*.mp4 *.mkv *.avi *.webm)",
"Audio files (*.mp3 *.wav *.flac *.ogg *.m4a *.mka)",
"Documents (*.doc *.docx *.odt)",
"All files (*)"
]
// TODO: support multiple files
// Currently the problem is that the fileUrls list isn't cleared
onAccepted: {
console.log("You chose: " + fileDialog.fileUrls)
}
onRejected: {
console.log("Canceled")
console.log("You chose: " + fileUrl)
kaidan.sendFile(recipientJid, fileUrl)
}
}
......@@ -82,7 +87,7 @@ Kirigami.ScrollablePage {
IconButton {
buttonText: qsTr("Audio")
iconSource: "audio-mp3"
onClicked: openFileDialog("Audio Files (*.mp3 *.wav *.flac *.ogg *.m4a *.mka)")
onClicked: openFileDialog("Audio files (*.mp3 *.wav *.flac *.ogg *.m4a *.mka)")
Layout.alignment: Qt.AlignHCenter
}
IconButton {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment