Verified Commit b1cc9e63 authored by Linus Jahn's avatar Linus Jahn Committed by Linus Jahn

Send and receive SIMS messages

parent 975f4c31
......@@ -57,6 +57,7 @@
#include <gloox/delayeddelivery.h>
#include "gloox-extensions/httpuploadrequest.h"
#include "gloox-extensions/httpuploadslot.h"
#include "gloox-extensions/reference.h"
// package fetch interval in ms
static const unsigned int KAIDAN_CLIENT_LOOP_INTERVAL = 30;
......@@ -138,6 +139,7 @@ void ClientThread::run()
client->registerStanzaExtension(new gloox::VCardUpdate());
client->registerStanzaExtension(new gloox::HttpUploadRequest());
client->registerStanzaExtension(new gloox::HttpUploadSlot());
client->registerStanzaExtension(new gloox::Reference(gloox::Reference::Data));
// connect slots
connect(this, &ClientThread::sendMessageRequested,
......@@ -148,6 +150,8 @@ void ClientThread::run()
uploadHandler, &UploadHandler::uploadFile);
connect(this, &ClientThread::addContactRequested,
rosterManager, &RosterManager::addContact);
connect(uploadHandler, &UploadHandler::uploadProgressMade,
kaidan, &Kaidan::uploadProgressMade);
connect(this, &ClientThread::removeContactRequested,
rosterManager, &RosterManager::removeContact);
connect(kaidan, &Kaidan::vCardRequested, [=](QString jid) {
......
......@@ -189,7 +189,7 @@ signals:
/**
* Emit to start uploading and sending a file
*/
void sendFileRequested(QString jid, QString filePath);
void sendFileRequested(QString jid, QString filePath, QString message);
/**
* Emit to add a new contact to the roster.
......
......@@ -213,12 +213,12 @@ void Kaidan::sendMessage(QString jid, QString message)
}
}
void Kaidan::sendFile(QString jid, QString filePath)
void Kaidan::sendFile(QString jid, QString filePath, QString message)
{
if (client->isConnected()) {
// convert file-URLs to file paths
filePath.replace("file://", "");
emit client->sendFileRequested(jid, filePath);
emit client->sendFileRequested(jid, filePath, message);
} 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.";
......
......@@ -124,7 +124,7 @@ public:
/**
* Upload and send file
*/
Q_INVOKABLE void sendFile(QString jid, QString filePath);
Q_INVOKABLE void sendFile(QString jid, QString filePath, QString message);
/**
* Add a contact to your roster
......@@ -345,7 +345,7 @@ signals:
void subscriptionRequestAnswered(QString jid, bool accepted);
/**
* Request VCard of any JID
* Request vCard of any JID
*
* Is required when the avatar (or other information) of a JID are
* requested and the JID is not in the roster.
......@@ -359,6 +359,11 @@ signals:
*/
void xmppUriReceived(QString uri);
/**
* The upload progress of a file upload has changed
*/
void uploadProgressMade(QString msgId, unsigned long sent, unsigned long total);
public slots:
/**
* Receives messages from another instance of the application
......
......@@ -35,12 +35,18 @@
#include <QDateTime>
#include <QDebug>
#include <QString>
#include <QMimeDatabase>
#include <QMimeType>
// gloox
#include <gloox/client.h>
#include <gloox/message.h>
#include <gloox/messagesession.h>
#include <gloox/receipt.h>
#include <gloox/carbons.h>
#include "gloox-extensions/gloox-extensions.h"
#include "gloox-extensions/reference.h"
#include "gloox-extensions/sims.h"
#include "gloox-extensions/jinglefile.h"
// Kaidan
#include "MessageModel.h"
#include "Notifications.h"
......@@ -115,6 +121,36 @@ void MessageHandler::handleMessage(const gloox::Message &stanza, gloox::MessageS
msg.recipientResource = QString::fromStdString(message->to().resource());
msg.id = QString::fromStdString(message->id());
msg.sentByMe = (msg.author == QString::fromStdString(client->jid().bare()));
msg.message = body;
msg.type = MessageType::MessageText; // only text, no media
//
// Get media sharing (SIMS) information
//
const gloox::Reference *ref = message->findExtension
<gloox::Reference>(gloox::EXT_REFERENCES);
if (ref && ref->getEmbeddedSIMS()) {
gloox::SIMS *sims = ref->getEmbeddedSIMS();
gloox::StringList sources = sims->sources();
for (auto &source : sources) {
if (source.rfind("https://", 0) == 0 ||
source.rfind("http://", 0) == 0) {
msg.mediaUrl = QString::fromStdString(source);
break;
}
}
gloox::Jingle::File *file = sims->file();
if (file && file->valid()) {
msg.message = QString::fromStdString(file->desc());
msg.mediaSize = file->size();
msg.mediaContentType = QString::fromStdString(file->mediaType());
msg.mediaLastModified = stringToQDateTime(file->date()).toTime_t();
QMimeType mimeType = QMimeDatabase().mimeTypeForName(msg.mediaContentType);
msg.type = getMessageType(mimeType);
}
}
//
// If it is a delayed delivery (containing a timestamp), use its timestamp
......@@ -261,3 +297,21 @@ void MessageHandler::resetUnreadMessagesForJid(const QString &jid)
// reset the unread message count to 0
emit rosterModel->setUnreadMessageCountRequested(jid, 0);
}
MessageType MessageHandler::getMessageType(QMimeType& type)
{
if (type.inherits("image/jpeg") || type.inherits("image/png") ||
type.inherits("image/gif"))
return MessageType::MessageImage;
else if (type.inherits("audio/flac") || type.inherits("audio/mp4") ||
type.inherits("audio/ogg") || type.inherits("audio/wav") ||
type.inherits("audio/mpeg") || type.inherits("audio/webm"))
return MessageType::MessageAudio;
else if (type.inherits("video/mpeg") || type.inherits("video/x-msvideo") ||
type.inherits("video/quicktime") || type.inherits("video/mp4") ||
type.inherits("video/x-matroska"))
return MessageType::MessageVideo;
else if (type.inherits("text/plain"))
return MessageType::MessageDocument;
return MessageType::MessageFile;
}
......@@ -47,8 +47,13 @@ namespace gloox {
class MessageSession;
}
class QMimeType;
using namespace Enums;
/**
* @class MessageHandler Handler for incoming and outgoing messages
*/
class MessageHandler : public QObject, public gloox::MessageHandler
{
Q_OBJECT
......@@ -91,6 +96,11 @@ public:
void addMessageToDb(QString &toJid, QString &body, QString id,
MessageType type, QString mediaLocation = "");
/**
* Get the message type from mime type
*/
MessageType getMessageType(QMimeType &type);
public slots:
void setChatPartner(QString chatPartner);
void sendMessage(QString toJid, QString body);
......
......@@ -55,7 +55,7 @@ UploadHandler::UploadHandler(gloox::Client *client, MessageHandler *msgHandler,
manager->registerHttpUploadHandler(this);
}
void UploadHandler::uploadFile(QString jid, QString filePath)
void UploadHandler::uploadFile(QString jid, QString filePath, QString message)
{
// get MIME-type
QMimeDatabase mimeDb;
......@@ -74,13 +74,14 @@ void UploadHandler::uploadFile(QString jid, QString filePath)
MediaSharingMeta meta;
meta.jid = jid;
meta.msgId = client->getID();
meta.message = message;
mediaShares[id] = meta;
QString body = "";
MessageType type = msgHandler->getMessageType(mimeType);
msgHandler->addMessageToDb(
jid, body, QString::fromStdString(meta.msgId),
getMessageType(mimeType), filePath
jid, message, QString::fromStdString(meta.msgId),
MessageType::MessageFile, filePath
);
}
}
......@@ -109,10 +110,41 @@ void UploadHandler::handleUploadFinished(int id, std::string &name,
QString::fromStdString(mediaShares[id].msgId), msg
);
// TODO: send SIMS message (and optionally also create jingle object)
// for now only send a normal text message with the get URL.
QString body = QString::fromStdString(getUrl);
msgHandler->sendOnlyMessage(mediaShares[id].jid, body, mediaShares[id].msgId);
//
// Create SIMS element
//
// TODO: generate thumbnail
// TODO: hashes
// TODO: lastModified / date
std::string date = "";
gloox::Jingle::File *fileInfo = new gloox::Jingle::File(
name, size, std::list<gloox::Hash>(), contentType, date,
mediaShares[id].message.toStdString()
);
// list of sources for the file (TODO: jingle as fallback)
gloox::StringList sources;
sources.emplace_back(getUrl);
gloox::SIMS *sims = new gloox::SIMS(fileInfo, sources);
gloox::Reference *simsRef = new gloox::Reference(gloox::Reference::Data);
simsRef->embedSIMS(sims);
//
// Create message
//
gloox::JID to(mediaShares[id].jid.toStdString());
// message body for clients without SIMS support
std::string msgBody = getUrl;
if (!mediaShares[id].message.isEmpty())
msgBody = msgBody.append("\n").append(mediaShares[id].message.toStdString());
gloox::Message message(gloox::Message::Chat, to.bareJID(), msgBody);
message.setID(mediaShares[id].msgId);
message.addExtension((gloox::StanzaExtension*) simsRef);
client->send(message);
// the media meta isn't needed anymore, so delete it
mediaShares.remove(id);
......@@ -135,21 +167,3 @@ void UploadHandler::handleUploadServiceAdded(const gloox::JID &jid,
void UploadHandler::handleFileSizeLimitChanged(unsigned long maxFileSize)
{
}
MessageType UploadHandler::getMessageType(QMimeType& type)
{
if (type.inherits("image/jpeg") || type.inherits("image/png") ||
type.inherits("image/gif"))
return MessageType::MessageImage;
else if (type.inherits("audio/flac") || type.inherits("audio/mp4") ||
type.inherits("audio/ogg") || type.inherits("audio/wav") ||
type.inherits("audio/mpeg") || type.inherits("audio/webm"))
return MessageType::MessageAudio;
else if (type.inherits("video/mpeg") || type.inherits("video/x-msvideo") ||
type.inherits("video/quicktime") || type.inherits("video/mp4") ||
type.inherits("video/x-matroska"))
return MessageType::MessageVideo;
else if (type.inherits("text/plain"))
return MessageType::MessageDocument;
return MessageType::MessageFile;
}
......@@ -31,8 +31,6 @@
#ifndef UPLOADHANDLER_H
#define UPLOADHANDLER_H
// Kaidan
#include "Enums.h"
// gloox
#include "gloox-extensions/httpuploadhandler.h"
#include "gloox-extensions/httpuploadmanager.h"
......@@ -44,13 +42,10 @@ namespace gloox {
class Client;
}
class QMimeType;
class MessageHandler;
class MessageModel;
class QtHttpUploader;
using namespace Enums;
/**
* @class UploadHandler Class for handling and starting HTTP File Uploads
*/
......@@ -79,10 +74,8 @@ signals:
public slots:
/**
* Starts uploading a file
*
* @todo also add entry to database
*/
void uploadFile(QString jid, QString filePath);
void uploadFile(QString jid, QString filePath, QString message);
protected:
/**
......@@ -140,11 +133,10 @@ protected:
const std::string &stamp = gloox::EmptyString);
private:
MessageType getMessageType(QMimeType &type);
struct MediaSharingMeta {
QString jid;
std::string msgId;
QString message;
};
gloox::Client *client;
......
......@@ -59,8 +59,8 @@ Kirigami.ScrollablePage {
// TODO: support multiple files
// Currently the problem is that the fileUrls list isn't cleared
onAccepted: {
console.log("You chose: " + fileUrl)
kaidan.sendFile(recipientJid, fileUrl)
// TODO: Add sheet for entering description, maybe later also image cropping
kaidan.sendFile(recipientJid, fileUrl, "")
}
}
......
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