fileUpload #30
@ -23,7 +23,7 @@
|
||||
|
||||
using namespace Core;
|
||||
|
||||
Account::Account(const QString& p_login, const QString& p_server, const QString& p_password, const QString& p_name, QObject* parent):
|
||||
Account::Account(const QString& p_login, const QString& p_server, const QString& p_password, const QString& p_name, NetworkAccess* p_net, QObject* parent):
|
||||
QObject(parent),
|
||||
name(p_name),
|
||||
achiveQueries(),
|
||||
@ -38,15 +38,19 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
bm(new QXmppBookmarkManager()),
|
||||
rm(client.findExtension<QXmppRosterManager>()),
|
||||
vm(client.findExtension<QXmppVCardManager>()),
|
||||
um(new QXmppUploadRequestManager()),
|
||||
contacts(),
|
||||
conferences(),
|
||||
maxReconnectTimes(0),
|
||||
reconnectTimes(0),
|
||||
queuedContacts(),
|
||||
outOfRosterContacts(),
|
||||
pendingMessages(),
|
||||
uploadingSlotsQueue(),
|
||||
avatarHash(),
|
||||
avatarType(),
|
||||
ownVCardRequestInProgress(false)
|
||||
ownVCardRequestInProgress(false),
|
||||
network(p_net)
|
||||
{
|
||||
config.setUser(p_login);
|
||||
config.setDomain(p_server);
|
||||
@ -85,6 +89,10 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
QObject::connect(vm, &QXmppVCardManager::vCardReceived, this, &Account::onVCardReceived);
|
||||
//QObject::connect(&vm, &QXmppVCardManager::clientVCardReceived, this, &Account::onOwnVCardReceived); //for some reason it doesn't work, launching from common handler
|
||||
|
||||
client.addExtension(um);
|
||||
QObject::connect(um, &QXmppUploadRequestManager::slotReceived, this, &Account::onUploadSlotReceived);
|
||||
QObject::connect(um, &QXmppUploadRequestManager::requestFailed, this, &Account::onUploadSlotRequestFailed);
|
||||
|
||||
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
||||
path += "/" + name;
|
||||
QDir dir(path);
|
||||
@ -141,6 +149,7 @@ Account::~Account()
|
||||
delete itr->second;
|
||||
}
|
||||
|
||||
delete um;
|
||||
delete bm;
|
||||
delete mm;
|
||||
delete am;
|
||||
@ -623,6 +632,44 @@ void Core::Account::sendMessage(const Shared::Message& data)
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Account::sendMessage(const Shared::Message& data, const QString& path)
|
||||
{
|
||||
if (state == Shared::connected) {
|
||||
QString url = network->getFileRemoteUrl(path);
|
||||
if (url.size() != 0) {
|
||||
sendMessageWithLocalUploadedFile(data, url);
|
||||
} else {
|
||||
if (network->isUploading(path, data.getId())) {
|
||||
pendingMessages.emplace(data.getId(), data);
|
||||
} else {
|
||||
if (um->serviceFound()) {
|
||||
QFileInfo file(path);
|
||||
if (file.exists() && file.isReadable()) {
|
||||
uploadingSlotsQueue.emplace_back(path, data);
|
||||
if (uploadingSlotsQueue.size() == 1) {
|
||||
um->requestUploadSlot(file);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Requested upload slot in account" << name << "for file" << path << "but the file doesn't exist or is not readable";
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Requested upload slot in account" << name << "for file" << path << "but upload manager didn't discover any upload services";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qDebug() << "An attempt to send message with not connected account " << name << ", skipping";
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Account::sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url)
|
||||
{
|
||||
msg.setOutOfBandUrl(url);
|
||||
sendMessage(msg);
|
||||
//TODO removal/progress update
|
||||
}
|
||||
|
||||
|
||||
void Core::Account::onCarbonMessageReceived(const QXmppMessage& msg)
|
||||
{
|
||||
handleChatMessage(msg, false, true);
|
||||
@ -1551,3 +1598,45 @@ void Core::Account::uploadVCard(const Shared::VCard& card)
|
||||
vm->setClientVCard(iq);
|
||||
onOwnVCardReceived(iq);
|
||||
}
|
||||
|
||||
void Core::Account::onUploadSlotReceived(const QXmppHttpUploadSlotIq& slot)
|
||||
{
|
||||
if (uploadingSlotsQueue.size() == 0) {
|
||||
qDebug() << "HTTP Upload manager of account" << name << "reports about success requesting upload slot, but none was requested";
|
||||
} else {
|
||||
const std::pair<QString, Shared::Message>& pair = uploadingSlotsQueue.front();
|
||||
const QString& mId = pair.second.getId();
|
||||
network->uploadFile(mId, pair.first, slot.putUrl(), slot.getUrl(), slot.putHeaders());
|
||||
pendingMessages.emplace(mId, pair.second);
|
||||
uploadingSlotsQueue.pop_front();
|
||||
|
||||
if (uploadingSlotsQueue.size() > 0) {
|
||||
um->requestUploadSlot(uploadingSlotsQueue.front().first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Account::onUploadSlotRequestFailed(const QXmppHttpUploadRequestIq& request)
|
||||
{
|
||||
if (uploadingSlotsQueue.size() == 0) {
|
||||
qDebug() << "HTTP Upload manager of account" << name << "reports about an error requesting upload slot, but none was requested";
|
||||
qDebug() << request.error().text();
|
||||
} else {
|
||||
const std::pair<QString, Shared::Message>& pair = uploadingSlotsQueue.front();
|
||||
qDebug() << "Error requesting upload slot for file" << pair.first << "in account" << name << ":" << request.error().text();
|
||||
|
||||
if (uploadingSlotsQueue.size() > 0) {
|
||||
um->requestUploadSlot(uploadingSlotsQueue.front().first);
|
||||
}
|
||||
uploadingSlotsQueue.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Account::onFileUploaded(const QString& messageId, const QString& url)
|
||||
{
|
||||
std::map<QString, Shared::Message>::const_iterator itr = pendingMessages.find(messageId);
|
||||
if (itr != pendingMessages.end()) {
|
||||
sendMessageWithLocalUploadedFile(itr->second, url);
|
||||
pendingMessages.erase(itr);
|
||||
}
|
||||
}
|
||||
|
@ -36,12 +36,14 @@
|
||||
#include <QXmppClient.h>
|
||||
#include <QXmppBookmarkManager.h>
|
||||
#include <QXmppBookmarkSet.h>
|
||||
#include <QXmppUploadRequestManager.h>
|
||||
#include <QXmppHttpUploadIq.h>
|
||||
#include <QXmppVCardIq.h>
|
||||
#include <QXmppVCardManager.h>
|
||||
#include "../global.h"
|
||||
#include "global.h"
|
||||
#include "contact.h"
|
||||
#include "conference.h"
|
||||
#include "networkaccess.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
@ -50,7 +52,7 @@ class Account : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Account(const QString& p_login, const QString& p_server, const QString& p_password, const QString& p_name, QObject* parent = 0);
|
||||
Account(const QString& p_login, const QString& p_server, const QString& p_password, const QString& p_name, NetworkAccess* p_net, QObject* parent = 0);
|
||||
~Account();
|
||||
|
||||
void connect();
|
||||
@ -74,6 +76,7 @@ public:
|
||||
void setAvailability(Shared::Availability avail);
|
||||
QString getFullJid() const;
|
||||
void sendMessage(const Shared::Message& data);
|
||||
void sendMessage(const Shared::Message& data, const QString& path);
|
||||
void requestArchive(const QString& jid, int count, const QString& before);
|
||||
void setReconnectTimes(unsigned int times);
|
||||
void subscribeToContact(const QString& jid, const QString& reason);
|
||||
@ -113,6 +116,7 @@ signals:
|
||||
void changeRoomParticipant(const QString& jid, const QString& nickName, const QMap<QString, QVariant>& data);
|
||||
void removeRoomParticipant(const QString& jid, const QString& nickName);
|
||||
void receivedVCard(const QString& jid, const Shared::VCard& card);
|
||||
void uploadFile(const QFileInfo& file, const QUrl& set, const QUrl& get, QMap<QString, QString> headers);
|
||||
|
||||
private:
|
||||
QString name;
|
||||
@ -128,6 +132,7 @@ private:
|
||||
QXmppBookmarkManager* bm;
|
||||
QXmppRosterManager* rm;
|
||||
QXmppVCardManager* vm;
|
||||
QXmppUploadRequestManager* um;
|
||||
std::map<QString, Contact*> contacts;
|
||||
std::map<QString, Conference*> conferences;
|
||||
unsigned int maxReconnectTimes;
|
||||
@ -136,10 +141,13 @@ private:
|
||||
std::map<QString, QString> queuedContacts;
|
||||
std::set<QString> outOfRosterContacts;
|
||||
std::set<QString> pendingVCardRequests;
|
||||
std::map<QString, Shared::Message> pendingMessages;
|
||||
std::deque<std::pair<QString, Shared::Message>> uploadingSlotsQueue;
|
||||
|
||||
QString avatarHash;
|
||||
QString avatarType;
|
||||
bool ownVCardRequestInProgress;
|
||||
NetworkAccess* network;
|
||||
|
||||
private slots:
|
||||
void onClientConnected();
|
||||
@ -185,6 +193,11 @@ private slots:
|
||||
void onVCardReceived(const QXmppVCardIq& card);
|
||||
void onOwnVCardReceived(const QXmppVCardIq& card);
|
||||
|
||||
void onUploadSlotReceived(const QXmppHttpUploadSlotIq& slot);
|
||||
void onUploadSlotRequestFailed(const QXmppHttpUploadRequestIq& request);
|
||||
void onFileUploaded(const QString& messageId, const QString& url);
|
||||
void onFileUploadError(const QString& messageId, const QString& path);
|
||||
|
||||
private:
|
||||
void addedAccount(const QString &bareJid);
|
||||
void handleNewContact(Contact* contact);
|
||||
@ -200,7 +213,7 @@ private:
|
||||
void logMessage(const QXmppMessage& msg, const QString& reason = "Message wasn't handled: ");
|
||||
void storeConferences();
|
||||
void clearConferences();
|
||||
|
||||
void sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url);
|
||||
};
|
||||
|
||||
void initializeVCard(Shared::VCard& vCard, const QXmppVCardIq& card);
|
||||
|
@ -121,7 +121,7 @@ void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesT
|
||||
QString url = rpl->url().toString();
|
||||
std::map<QString, Transfer*>::const_iterator itr = downloads.find(url);
|
||||
if (itr == downloads.end()) {
|
||||
qDebug() << "an error downloading" << url << ": the request had some progress but seems like noone is waiting for it, skipping";
|
||||
qDebug() << "an error downloading" << url << ": the request had some progress but seems like no one is waiting for it, skipping";
|
||||
} else {
|
||||
Transfer* dwn = itr->second;
|
||||
qreal received = bytesReceived;
|
||||
@ -140,7 +140,7 @@ void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code)
|
||||
QString url = rpl->url().toString();
|
||||
std::map<QString, Transfer*>::const_iterator itr = downloads.find(url);
|
||||
if (itr == downloads.end()) {
|
||||
qDebug() << "an error downloading" << url << ": the request is reporting an error but seems like noone is waiting for it, skipping";
|
||||
qDebug() << "an error downloading" << url << ": the request is reporting an error but seems like no one is waiting for it, skipping";
|
||||
} else {
|
||||
QString errorText = getErrorText(code);
|
||||
if (errorText.size() > 0) {
|
||||
@ -328,7 +328,7 @@ void Core::NetworkAccess::onDownloadFinished()
|
||||
|
||||
void Core::NetworkAccess::startDownload(const QString& messageId, const QString& url)
|
||||
{
|
||||
Transfer* dwn = new Transfer({{messageId}, 0, 0, true, "", 0});
|
||||
Transfer* dwn = new Transfer({{messageId}, 0, 0, true, "", url, 0});
|
||||
QNetworkRequest req(url);
|
||||
dwn->reply = manager->get(req);
|
||||
connect(dwn->reply, &QNetworkReply::downloadProgress, this, &NetworkAccess::onDownloadProgress);
|
||||
@ -363,15 +363,16 @@ void Core::NetworkAccess::onUploadFinished()
|
||||
QString url = rpl->url().toString();
|
||||
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
||||
if (itr == downloads.end()) {
|
||||
qDebug() << "an error uploading" << url << ": the request is done but seems like noone is waiting for it, skipping";
|
||||
qDebug() << "an error uploading" << url << ": the request is done but seems like no one is waiting for it, skipping";
|
||||
} else {
|
||||
Transfer* upl = itr->second;
|
||||
if (upl->success) {
|
||||
qDebug() << "upload success for" << url;
|
||||
files.addRecord(url, upl->path);
|
||||
files.addRecord(upl->url, upl->path);
|
||||
|
||||
for (std::set<QString>::const_iterator mItr = upl->messages.begin(), end = upl->messages.end(); mItr != end; ++mItr) {
|
||||
emit fileLocalPathResponse(*mItr, upl->path);
|
||||
emit uploadFileComplete(*mItr, upl->url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,7 +390,7 @@ void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTot
|
||||
QString url = rpl->url().toString();
|
||||
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
||||
if (itr == uploads.end()) {
|
||||
qDebug() << "an error downloading" << url << ": the request had some progress but seems like noone is waiting for it, skipping";
|
||||
qDebug() << "an error downloading" << url << ": the request had some progress but seems like no one is waiting for it, skipping";
|
||||
} else {
|
||||
Transfer* upl = itr->second;
|
||||
qreal received = bytesReceived;
|
||||
@ -404,15 +405,15 @@ void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTot
|
||||
|
||||
void Core::NetworkAccess::startUpload(const QString& messageId, const QString& url, const QString& path)
|
||||
{
|
||||
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, 0});
|
||||
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, url, 0});
|
||||
QNetworkRequest req(url);
|
||||
QFile* file = new QFile(path);
|
||||
if (file->open(QIODevice::ReadOnly)) {
|
||||
upl->reply = manager->put(req, file);
|
||||
|
||||
connect(upl->reply, SIGNAL(uploadProgress(qint64, qint64)), SLOT(onUploadProgress(qint64, qint64)));
|
||||
connect(upl->reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(onUploadError(QNetworkReply::NetworkError)));
|
||||
connect(upl->reply, SIGNAL(finished()), SLOT(onUploadFinished()));
|
||||
connect(upl->reply, &QNetworkReply::uploadProgress, this, &NetworkAccess::onUploadProgress);
|
||||
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this, &NetworkAccess::onUploadError);
|
||||
connect(upl->reply, &QNetworkReply::finished, this, &NetworkAccess::onUploadFinished);
|
||||
uploads.insert(std::make_pair(url, upl));
|
||||
emit downloadFileProgress(messageId, 0);
|
||||
} else {
|
||||
@ -455,3 +456,36 @@ void Core::NetworkAccess::uploadFileRequest(const QString& messageId, const QStr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString Core::NetworkAccess::getFileRemoteUrl(const QString& path)
|
||||
{
|
||||
return ""; //TODO this is a way not to upload some file more then 1 time, here I'm supposed to return that file GET url
|
||||
}
|
||||
|
||||
bool Core::NetworkAccess::isUploading(const QString& path, const QString& messageId)
|
||||
{
|
||||
return false; //TODO this is a way to avoid parallel uploading of the same files by different chats
|
||||
// message is is supposed to be added to the uploading messageids list
|
||||
// the result should be true if there was an uploading file with this path
|
||||
// message id can be empty, then it's just to check and not to add
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::uploadFile(const QString& messageId, const QString& path, const QUrl& put, const QUrl& get, const QMap<QString, QString> headers)
|
||||
{
|
||||
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, get.toString(), 0});
|
||||
QNetworkRequest req(put);
|
||||
QFile* file = new QFile(path);
|
||||
if (file->open(QIODevice::ReadOnly)) {
|
||||
upl->reply = manager->put(req, file);
|
||||
|
||||
connect(upl->reply, &QNetworkReply::uploadProgress, this, &NetworkAccess::onUploadProgress);
|
||||
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this, &NetworkAccess::onUploadError);
|
||||
connect(upl->reply, &QNetworkReply::finished, this, &NetworkAccess::onUploadFinished);
|
||||
uploads.insert(std::make_pair(put.toString(), upl));
|
||||
emit downloadFileProgress(messageId, 0);
|
||||
} else {
|
||||
qDebug() << "couldn't upload file" << path;
|
||||
emit uploadFileError(messageId, "Error opening file");
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
|
@ -47,12 +47,17 @@ public:
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
QString getFileRemoteUrl(const QString& path);
|
||||
bool isUploading(const QString& path, const QString& messageId = "");
|
||||
void uploadFile(const QString& messageId, const QString& path, const QUrl& put, const QUrl& get, const QMap<QString, QString> headers);
|
||||
|
||||
signals:
|
||||
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
||||
void downloadFileProgress(const QString& messageId, qreal value);
|
||||
void downloadFileError(const QString& messageId, const QString& path);
|
||||
void uploadFileProgress(const QString& messageId, qreal value);
|
||||
void uploadFileError(const QString& messageId, const QString& path);
|
||||
void uploadFileComplete(const QString& messageId, const QString& url);
|
||||
|
||||
public slots:
|
||||
void fileLocalPathRequest(const QString& messageId, const QString& url);
|
||||
@ -85,6 +90,7 @@ private:
|
||||
QNetworkReply* reply;
|
||||
bool success;
|
||||
QString path;
|
||||
QString url;
|
||||
QFile* file;
|
||||
};
|
||||
};
|
||||
|
@ -106,7 +106,7 @@ void Core::Squawk::addAccount(const QString& login, const QString& server, const
|
||||
QSettings settings;
|
||||
unsigned int reconnects = settings.value("reconnects", 2).toUInt();
|
||||
|
||||
Account* acc = new Account(login, server, password, name);
|
||||
Account* acc = new Account(login, server, password, name, &network);
|
||||
acc->setResource(resource);
|
||||
acc->setReconnectTimes(reconnects);
|
||||
accounts.push_back(acc);
|
||||
@ -285,7 +285,13 @@ void Core::Squawk::sendMessage(const QString& account, const Shared::Message& da
|
||||
|
||||
void Core::Squawk::sendMessage(const QString& account, const Shared::Message& data, const QString& path)
|
||||
{
|
||||
AccountsMap::const_iterator itr = amap.find(account);
|
||||
if (itr == amap.end()) {
|
||||
qDebug("An attempt to send a message with non existing account, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
itr->second->sendMessage(data, path);
|
||||
}
|
||||
|
||||
void Core::Squawk::requestArchive(const QString& account, const QString& jid, int count, const QString& before)
|
||||
|
Loading…
Reference in New Issue
Block a user