fileUpload #30
@ -30,6 +30,7 @@
|
|||||||
#include <QXmppClient.h>
|
#include <QXmppClient.h>
|
||||||
#include <QXmppBookmarkManager.h>
|
#include <QXmppBookmarkManager.h>
|
||||||
#include <QXmppBookmarkSet.h>
|
#include <QXmppBookmarkSet.h>
|
||||||
|
#include <QXmppHttpUploadIq.h>
|
||||||
#include "../global.h"
|
#include "../global.h"
|
||||||
#include "contact.h"
|
#include "contact.h"
|
||||||
#include "conference.h"
|
#include "conference.h"
|
||||||
|
@ -23,7 +23,8 @@ Core::NetworkAccess::NetworkAccess(QObject* parent):
|
|||||||
running(false),
|
running(false),
|
||||||
manager(0),
|
manager(0),
|
||||||
files("files"),
|
files("files"),
|
||||||
downloads()
|
downloads(),
|
||||||
|
uploads()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,9 +35,9 @@ Core::NetworkAccess::~NetworkAccess()
|
|||||||
|
|
||||||
void Core::NetworkAccess::fileLocalPathRequest(const QString& messageId, const QString& url)
|
void Core::NetworkAccess::fileLocalPathRequest(const QString& messageId, const QString& url)
|
||||||
{
|
{
|
||||||
std::map<QString, Download*>::iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
||||||
if (itr != downloads.end()) {
|
if (itr != downloads.end()) {
|
||||||
Download* dwn = itr->second;
|
Transfer* dwn = itr->second;
|
||||||
std::set<QString>::const_iterator mItr = dwn->messages.find(messageId);
|
std::set<QString>::const_iterator mItr = dwn->messages.find(messageId);
|
||||||
if (mItr == dwn->messages.end()) {
|
if (mItr == dwn->messages.end()) {
|
||||||
dwn->messages.insert(messageId);
|
dwn->messages.insert(messageId);
|
||||||
@ -63,9 +64,9 @@ void Core::NetworkAccess::fileLocalPathRequest(const QString& messageId, const Q
|
|||||||
|
|
||||||
void Core::NetworkAccess::downladFileRequest(const QString& messageId, const QString& url)
|
void Core::NetworkAccess::downladFileRequest(const QString& messageId, const QString& url)
|
||||||
{
|
{
|
||||||
std::map<QString, Download*>::iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
||||||
if (itr != downloads.end()) {
|
if (itr != downloads.end()) {
|
||||||
Download* dwn = itr->second;
|
Transfer* dwn = itr->second;
|
||||||
std::set<QString>::const_iterator mItr = dwn->messages.find(messageId);
|
std::set<QString>::const_iterator mItr = dwn->messages.find(messageId);
|
||||||
if (mItr == dwn->messages.end()) {
|
if (mItr == dwn->messages.end()) {
|
||||||
dwn->messages.insert(messageId);
|
dwn->messages.insert(messageId);
|
||||||
@ -85,7 +86,7 @@ void Core::NetworkAccess::downladFileRequest(const QString& messageId, const QSt
|
|||||||
startDownload(messageId, url);
|
startDownload(messageId, url);
|
||||||
} catch (Archive::Unknown e) {
|
} catch (Archive::Unknown e) {
|
||||||
qDebug() << "Error requesting file path:" << e.what();
|
qDebug() << "Error requesting file path:" << e.what();
|
||||||
startDownload(messageId, url);
|
emit downloadFileError(messageId, QString("Database error: ") + e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +108,7 @@ void Core::NetworkAccess::stop()
|
|||||||
manager = 0;
|
manager = 0;
|
||||||
running = false;
|
running = false;
|
||||||
|
|
||||||
for (std::map<QString, Download*>::const_iterator itr = downloads.begin(), end = downloads.end(); itr != end; ++itr) {
|
for (std::map<QString, Transfer*>::const_iterator itr = downloads.begin(), end = downloads.end(); itr != end; ++itr) {
|
||||||
itr->second->success = false;
|
itr->second->success = false;
|
||||||
itr->second->reply->abort(); //assuming it's gonna call onRequestFinished slot
|
itr->second->reply->abort(); //assuming it's gonna call onRequestFinished slot
|
||||||
}
|
}
|
||||||
@ -118,11 +119,11 @@ void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesT
|
|||||||
{
|
{
|
||||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Download*>::const_iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::const_iterator itr = downloads.find(url);
|
||||||
if (itr == downloads.end()) {
|
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 noone is waiting for it, skipping";
|
||||||
} else {
|
} else {
|
||||||
Download* dwn = itr->second;
|
Transfer* dwn = itr->second;
|
||||||
qreal received = bytesReceived;
|
qreal received = bytesReceived;
|
||||||
qreal total = bytesTotal;
|
qreal total = bytesTotal;
|
||||||
qreal progress = received/total;
|
qreal progress = received/total;
|
||||||
@ -133,132 +134,18 @@ void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::onRequestError(QNetworkReply::NetworkError code)
|
void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code)
|
||||||
{
|
{
|
||||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Download*>::const_iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::const_iterator itr = downloads.find(url);
|
||||||
if (itr == downloads.end()) {
|
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 noone is waiting for it, skipping";
|
||||||
} else {
|
} else {
|
||||||
QString errorText;
|
QString errorText = getErrorText(code);
|
||||||
switch (code) {
|
|
||||||
case QNetworkReply::NoError:
|
|
||||||
//this never is supposed to happen
|
|
||||||
break;
|
|
||||||
|
|
||||||
// network layer errors [relating to the destination server] (1-99):
|
|
||||||
case QNetworkReply::ConnectionRefusedError:
|
|
||||||
errorText = "Connection refused";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::RemoteHostClosedError:
|
|
||||||
errorText = "Remote server closed the connection";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::HostNotFoundError:
|
|
||||||
errorText = "Remote host is not found";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::TimeoutError:
|
|
||||||
errorText = "Connection was closed because it timed out";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::OperationCanceledError:
|
|
||||||
//this means I closed it myself by abort() or close(), don't think I need to notify here
|
|
||||||
break;
|
|
||||||
case QNetworkReply::SslHandshakeFailedError:
|
|
||||||
errorText = "Security error"; //TODO need to handle sslErrors signal to get a better description here
|
|
||||||
break;
|
|
||||||
case QNetworkReply::TemporaryNetworkFailureError:
|
|
||||||
//this means the connection is lost by opened route, but it's going to be resumed, not sure I need to notify
|
|
||||||
break;
|
|
||||||
case QNetworkReply::NetworkSessionFailedError:
|
|
||||||
errorText = "Outgoing connection problem";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::BackgroundRequestNotAllowedError:
|
|
||||||
errorText = "Background request is not allowed";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::TooManyRedirectsError:
|
|
||||||
errorText = "The request was redirected too many times";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::InsecureRedirectError:
|
|
||||||
errorText = "The request was redirected to insecure connection";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::UnknownNetworkError:
|
|
||||||
errorText = "Unknown network error";
|
|
||||||
break;
|
|
||||||
|
|
||||||
// proxy errors (101-199):
|
|
||||||
case QNetworkReply::ProxyConnectionRefusedError:
|
|
||||||
errorText = "The connection to the proxy server was refused";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ProxyConnectionClosedError:
|
|
||||||
errorText = "Proxy server closed the connection";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ProxyNotFoundError:
|
|
||||||
errorText = "Proxy host was not found";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ProxyTimeoutError:
|
|
||||||
errorText = "Connection to the proxy server was closed because it timed out";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ProxyAuthenticationRequiredError:
|
|
||||||
errorText = "Couldn't connect to proxy server, authentication is required";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::UnknownProxyError:
|
|
||||||
errorText = "Unknown proxy error";
|
|
||||||
break;
|
|
||||||
|
|
||||||
// content errors (201-299):
|
|
||||||
case QNetworkReply::ContentAccessDenied:
|
|
||||||
errorText = "The access to file is denied";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ContentOperationNotPermittedError:
|
|
||||||
errorText = "The operation over requesting file is not permitted";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ContentNotFoundError:
|
|
||||||
errorText = "The file was not found";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::AuthenticationRequiredError:
|
|
||||||
errorText = "Couldn't access the file, authentication is required";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ContentReSendError:
|
|
||||||
errorText = "Sending error, one more attempt will probably solve this problem";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ContentConflictError:
|
|
||||||
errorText = "The request could not be completed due to a conflict with the current state of the resource";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ContentGoneError:
|
|
||||||
errorText = "The requested resource is no longer available at the server";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::UnknownContentError:
|
|
||||||
errorText = "Unknown content error";
|
|
||||||
break;
|
|
||||||
|
|
||||||
// protocol errors
|
|
||||||
case QNetworkReply::ProtocolUnknownError:
|
|
||||||
errorText = "Unknown protocol error";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ProtocolInvalidOperationError:
|
|
||||||
errorText = "Requested operation is not permitted in this protocol";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ProtocolFailure:
|
|
||||||
errorText = "Low level protocol error";
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Server side errors (401-499)
|
|
||||||
case QNetworkReply::InternalServerError:
|
|
||||||
errorText = "Internal server error";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::OperationNotImplementedError:
|
|
||||||
errorText = "Server doesn't support requested operation";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::ServiceUnavailableError:
|
|
||||||
errorText = "The server is not available for this operation right now";
|
|
||||||
break;
|
|
||||||
case QNetworkReply::UnknownServerError:
|
|
||||||
errorText = "Unknown server error";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (errorText.size() > 0) {
|
if (errorText.size() > 0) {
|
||||||
itr->second->success = false;
|
itr->second->success = false;
|
||||||
Download* dwn = itr->second;
|
Transfer* dwn = itr->second;
|
||||||
for (std::set<QString>::const_iterator mItr = dwn->messages.begin(), end = dwn->messages.end(); mItr != end; ++mItr) {
|
for (std::set<QString>::const_iterator mItr = dwn->messages.begin(), end = dwn->messages.end(); mItr != end; ++mItr) {
|
||||||
emit downloadFileError(*mItr, errorText);
|
emit downloadFileError(*mItr, errorText);
|
||||||
}
|
}
|
||||||
@ -266,16 +153,137 @@ void Core::NetworkAccess::onRequestError(QNetworkReply::NetworkError code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::onRequestFinished()
|
QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code)
|
||||||
|
{
|
||||||
|
QString errorText("");
|
||||||
|
switch (code) {
|
||||||
|
case QNetworkReply::NoError:
|
||||||
|
//this never is supposed to happen
|
||||||
|
break;
|
||||||
|
|
||||||
|
// network layer errors [relating to the destination server] (1-99):
|
||||||
|
case QNetworkReply::ConnectionRefusedError:
|
||||||
|
errorText = "Connection refused";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::RemoteHostClosedError:
|
||||||
|
errorText = "Remote server closed the connection";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::HostNotFoundError:
|
||||||
|
errorText = "Remote host is not found";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::TimeoutError:
|
||||||
|
errorText = "Connection was closed because it timed out";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::OperationCanceledError:
|
||||||
|
//this means I closed it myself by abort() or close(), don't think I need to notify here
|
||||||
|
break;
|
||||||
|
case QNetworkReply::SslHandshakeFailedError:
|
||||||
|
errorText = "Security error"; //TODO need to handle sslErrors signal to get a better description here
|
||||||
|
break;
|
||||||
|
case QNetworkReply::TemporaryNetworkFailureError:
|
||||||
|
//this means the connection is lost by opened route, but it's going to be resumed, not sure I need to notify
|
||||||
|
break;
|
||||||
|
case QNetworkReply::NetworkSessionFailedError:
|
||||||
|
errorText = "Outgoing connection problem";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::BackgroundRequestNotAllowedError:
|
||||||
|
errorText = "Background request is not allowed";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::TooManyRedirectsError:
|
||||||
|
errorText = "The request was redirected too many times";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::InsecureRedirectError:
|
||||||
|
errorText = "The request was redirected to insecure connection";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::UnknownNetworkError:
|
||||||
|
errorText = "Unknown network error";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// proxy errors (101-199):
|
||||||
|
case QNetworkReply::ProxyConnectionRefusedError:
|
||||||
|
errorText = "The connection to the proxy server was refused";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ProxyConnectionClosedError:
|
||||||
|
errorText = "Proxy server closed the connection";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ProxyNotFoundError:
|
||||||
|
errorText = "Proxy host was not found";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ProxyTimeoutError:
|
||||||
|
errorText = "Connection to the proxy server was closed because it timed out";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ProxyAuthenticationRequiredError:
|
||||||
|
errorText = "Couldn't connect to proxy server, authentication is required";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::UnknownProxyError:
|
||||||
|
errorText = "Unknown proxy error";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// content errors (201-299):
|
||||||
|
case QNetworkReply::ContentAccessDenied:
|
||||||
|
errorText = "The access to file is denied";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ContentOperationNotPermittedError:
|
||||||
|
errorText = "The operation over requesting file is not permitted";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ContentNotFoundError:
|
||||||
|
errorText = "The file was not found";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::AuthenticationRequiredError:
|
||||||
|
errorText = "Couldn't access the file, authentication is required";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ContentReSendError:
|
||||||
|
errorText = "Sending error, one more attempt will probably solve this problem";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ContentConflictError:
|
||||||
|
errorText = "The request could not be completed due to a conflict with the current state of the resource";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ContentGoneError:
|
||||||
|
errorText = "The requested resource is no longer available at the server";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::UnknownContentError:
|
||||||
|
errorText = "Unknown content error";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// protocol errors
|
||||||
|
case QNetworkReply::ProtocolUnknownError:
|
||||||
|
errorText = "Unknown protocol error";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ProtocolInvalidOperationError:
|
||||||
|
errorText = "Requested operation is not permitted in this protocol";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ProtocolFailure:
|
||||||
|
errorText = "Low level protocol error";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Server side errors (401-499)
|
||||||
|
case QNetworkReply::InternalServerError:
|
||||||
|
errorText = "Internal server error";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::OperationNotImplementedError:
|
||||||
|
errorText = "Server doesn't support requested operation";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::ServiceUnavailableError:
|
||||||
|
errorText = "The server is not available for this operation right now";
|
||||||
|
break;
|
||||||
|
case QNetworkReply::UnknownServerError:
|
||||||
|
errorText = "Unknown server error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return errorText;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Core::NetworkAccess::onDownloadFinished()
|
||||||
{
|
{
|
||||||
QString path("");
|
QString path("");
|
||||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Download*>::const_iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::const_iterator itr = downloads.find(url);
|
||||||
if (itr == downloads.end()) {
|
if (itr == downloads.end()) {
|
||||||
qDebug() << "an error downloading" << url << ": the request is done but seems like noone is waiting for it, skipping";
|
qDebug() << "an error downloading" << url << ": the request is done but seems like noone is waiting for it, skipping";
|
||||||
} else {
|
} else {
|
||||||
Download* dwn = itr->second;
|
Transfer* dwn = itr->second;
|
||||||
if (dwn->success) {
|
if (dwn->success) {
|
||||||
qDebug() << "download success for" << url;
|
qDebug() << "download success for" << url;
|
||||||
QStringList hops = url.split("/");
|
QStringList hops = url.split("/");
|
||||||
@ -320,13 +328,130 @@ void Core::NetworkAccess::onRequestFinished()
|
|||||||
|
|
||||||
void Core::NetworkAccess::startDownload(const QString& messageId, const QString& url)
|
void Core::NetworkAccess::startDownload(const QString& messageId, const QString& url)
|
||||||
{
|
{
|
||||||
Download* dwn = new Download({{messageId}, 0, 0, true});
|
Transfer* dwn = new Transfer({{messageId}, 0, 0, true, "", 0});
|
||||||
QNetworkRequest req(url);
|
QNetworkRequest req(url);
|
||||||
dwn->reply = manager->get(req);
|
dwn->reply = manager->get(req);
|
||||||
connect(dwn->reply, SIGNAL(downloadProgress(qint64, qint64)), SLOT(onDownloadProgress(qint64, qint64)));
|
connect(dwn->reply, SIGNAL(downloadProgress(qint64, qint64)), SLOT(onDownloadProgress(qint64, qint64)));
|
||||||
connect(dwn->reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(onRequestError(QNetworkReply::NetworkError)));
|
connect(dwn->reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(onDownloadError(QNetworkReply::NetworkError)));
|
||||||
connect(dwn->reply, SIGNAL(finished()), SLOT(onRequestFinished()));
|
connect(dwn->reply, SIGNAL(finished()), SLOT(onDownloadFinished()));
|
||||||
downloads.insert(std::make_pair(url, dwn));
|
downloads.insert(std::make_pair(url, dwn));
|
||||||
emit downloadFileProgress(messageId, 0);
|
emit downloadFileProgress(messageId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code)
|
||||||
|
{
|
||||||
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
|
QString url = rpl->url().toString();
|
||||||
|
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
||||||
|
if (itr == uploads.end()) {
|
||||||
|
qDebug() << "an error uploading" << url << ": the request is reporting an error but seems like noone is waiting for it, skipping";
|
||||||
|
} else {
|
||||||
|
QString errorText = getErrorText(code);
|
||||||
|
if (errorText.size() > 0) {
|
||||||
|
itr->second->success = false;
|
||||||
|
Transfer* upl = itr->second;
|
||||||
|
for (std::set<QString>::const_iterator mItr = upl->messages.begin(), end = upl->messages.end(); mItr != end; ++mItr) {
|
||||||
|
emit uploadFileError(*mItr, errorText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::NetworkAccess::onUploadFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
|
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";
|
||||||
|
} else {
|
||||||
|
Transfer* upl = itr->second;
|
||||||
|
if (upl->success) {
|
||||||
|
qDebug() << "upload success for" << url;
|
||||||
|
files.addRecord(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
upl->reply->deleteLater();
|
||||||
|
upl->file->close();
|
||||||
|
upl->file->deleteLater();
|
||||||
|
delete upl;
|
||||||
|
uploads.erase(itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||||
|
{
|
||||||
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
|
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";
|
||||||
|
} else {
|
||||||
|
Transfer* upl = itr->second;
|
||||||
|
qreal received = bytesReceived;
|
||||||
|
qreal total = bytesTotal;
|
||||||
|
qreal progress = received/total;
|
||||||
|
upl->progress = progress;
|
||||||
|
for (std::set<QString>::const_iterator mItr = upl->messages.begin(), end = upl->messages.end(); mItr != end; ++mItr) {
|
||||||
|
emit uploadFileProgress(*mItr, progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::NetworkAccess::startUpload(const QString& messageId, const QString& url, const QString& path)
|
||||||
|
{
|
||||||
|
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, 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()));
|
||||||
|
uploads.insert(std::make_pair(url, upl));
|
||||||
|
emit downloadFileProgress(messageId, 0);
|
||||||
|
} else {
|
||||||
|
qDebug() << "couldn't upload file" << path;
|
||||||
|
emit uploadFileError(messageId, "Error opening file");
|
||||||
|
delete file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::NetworkAccess::uploadFileRequest(const QString& messageId, const QString& url, const QString& path)
|
||||||
|
{
|
||||||
|
std::map<QString, Transfer*>::iterator itr = uploads.find(url);
|
||||||
|
if (itr != uploads.end()) {
|
||||||
|
Transfer* upl = itr->second;
|
||||||
|
std::set<QString>::const_iterator mItr = upl->messages.find(messageId);
|
||||||
|
if (mItr == upl->messages.end()) {
|
||||||
|
upl->messages.insert(messageId);
|
||||||
|
}
|
||||||
|
emit uploadFileProgress(messageId, upl->progress);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
QString ePath = files.getRecord(url);
|
||||||
|
if (ePath == path) {
|
||||||
|
emit fileLocalPathResponse(messageId, path);
|
||||||
|
} else {
|
||||||
|
files.changeRecord(url, path);
|
||||||
|
}
|
||||||
|
QFileInfo info(path);
|
||||||
|
if (info.exists() && info.isFile()) {
|
||||||
|
emit fileLocalPathResponse(messageId, path);
|
||||||
|
} else {
|
||||||
|
files.removeRecord(url);
|
||||||
|
startDownload(messageId, url);
|
||||||
|
}
|
||||||
|
} catch (Archive::NotFound e) {
|
||||||
|
startUpload(messageId, url, path);
|
||||||
|
} catch (Archive::Unknown e) {
|
||||||
|
qDebug() << "Error requesting file path on upload:" << e.what();
|
||||||
|
emit uploadFileError(messageId, QString("Database error: ") + e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -39,7 +39,7 @@ namespace Core {
|
|||||||
class NetworkAccess : public QObject
|
class NetworkAccess : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
struct Download;
|
struct Transfer;
|
||||||
public:
|
public:
|
||||||
NetworkAccess(QObject* parent = nullptr);
|
NetworkAccess(QObject* parent = nullptr);
|
||||||
virtual ~NetworkAccess();
|
virtual ~NetworkAccess();
|
||||||
@ -51,30 +51,41 @@ signals:
|
|||||||
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
||||||
void downloadFileProgress(const QString& messageId, qreal value);
|
void downloadFileProgress(const QString& messageId, qreal value);
|
||||||
void downloadFileError(const QString& messageId, const QString& path);
|
void downloadFileError(const QString& messageId, const QString& path);
|
||||||
|
void uploadFileProgress(const QString& messageId, qreal value);
|
||||||
|
void uploadFileError(const QString& messageId, const QString& path);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void fileLocalPathRequest(const QString& messageId, const QString& url);
|
void fileLocalPathRequest(const QString& messageId, const QString& url);
|
||||||
void downladFileRequest(const QString& messageId, const QString& url);
|
void downladFileRequest(const QString& messageId, const QString& url);
|
||||||
|
void uploadFileRequest(const QString& messageId, const QString& url, const QString& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startDownload(const QString& messageId, const QString& url);
|
void startDownload(const QString& messageId, const QString& url);
|
||||||
|
void startUpload(const QString& messageId, const QString& url, const QString& path);
|
||||||
|
QString getErrorText(QNetworkReply::NetworkError code);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||||
void onRequestError(QNetworkReply::NetworkError code);
|
void onDownloadError(QNetworkReply::NetworkError code);
|
||||||
void onRequestFinished();
|
void onDownloadFinished();
|
||||||
|
void onUploadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||||
|
void onUploadError(QNetworkReply::NetworkError code);
|
||||||
|
void onUploadFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool running;
|
bool running;
|
||||||
QNetworkAccessManager* manager;
|
QNetworkAccessManager* manager;
|
||||||
Storage files;
|
Storage files;
|
||||||
std::map<QString, Download*> downloads;
|
std::map<QString, Transfer*> downloads;
|
||||||
|
std::map<QString, Transfer*> uploads;
|
||||||
|
|
||||||
struct Download {
|
struct Transfer {
|
||||||
std::set<QString> messages;
|
std::set<QString> messages;
|
||||||
qreal progress;
|
qreal progress;
|
||||||
QNetworkReply* reply;
|
QNetworkReply* reply;
|
||||||
bool success;
|
bool success;
|
||||||
|
QString path;
|
||||||
|
QFile* file;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ Core::Squawk::Squawk(QObject* parent):
|
|||||||
connect(&network, SIGNAL(fileLocalPathResponse(const QString&, const QString&)), this, SIGNAL(fileLocalPathResponse(const QString&, const QString&)));
|
connect(&network, SIGNAL(fileLocalPathResponse(const QString&, const QString&)), this, SIGNAL(fileLocalPathResponse(const QString&, const QString&)));
|
||||||
connect(&network, SIGNAL(downloadFileProgress(const QString&, qreal)), this, SIGNAL(downloadFileProgress(const QString&, qreal)));
|
connect(&network, SIGNAL(downloadFileProgress(const QString&, qreal)), this, SIGNAL(downloadFileProgress(const QString&, qreal)));
|
||||||
connect(&network, SIGNAL(downloadFileError(const QString&, const QString&)), this, SIGNAL(downloadFileError(const QString&, const QString&)));
|
connect(&network, SIGNAL(downloadFileError(const QString&, const QString&)), this, SIGNAL(downloadFileError(const QString&, const QString&)));
|
||||||
|
connect(&network, SIGNAL(uploadFileProgress(const QString&, qreal)), this, SIGNAL(uploadFileProgress(const QString&, qreal)));
|
||||||
|
connect(&network, SIGNAL(uploadFileError(const QString&, const QString&)), this, SIGNAL(uploadFileError(const QString&, const QString&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Squawk::~Squawk()
|
Core::Squawk::~Squawk()
|
||||||
@ -276,6 +278,11 @@ void Core::Squawk::sendMessage(const QString& account, const Shared::Message& da
|
|||||||
itr->second->sendMessage(data);
|
itr->second->sendMessage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::Squawk::sendMessage(const QString& account, const Shared::Message& data, const QString& path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Core::Squawk::requestArchive(const QString& account, const QString& jid, int count, const QString& before)
|
void Core::Squawk::requestArchive(const QString& account, const QString& jid, int count, const QString& before)
|
||||||
{
|
{
|
||||||
AccountsMap::const_iterator itr = amap.find(account);
|
AccountsMap::const_iterator itr = amap.find(account);
|
||||||
@ -368,7 +375,6 @@ void Core::Squawk::removeAccountRequest(const QString& name)
|
|||||||
acc->deleteLater();
|
acc->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Core::Squawk::subscribeContact(const QString& account, const QString& jid, const QString& reason)
|
void Core::Squawk::subscribeContact(const QString& account, const QString& jid, const QString& reason)
|
||||||
{
|
{
|
||||||
AccountsMap::const_iterator itr = amap.find(account);
|
AccountsMap::const_iterator itr = amap.find(account);
|
||||||
|
@ -65,6 +65,8 @@ signals:
|
|||||||
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
||||||
void downloadFileError(const QString& messageId, const QString& error);
|
void downloadFileError(const QString& messageId, const QString& error);
|
||||||
void downloadFileProgress(const QString& messageId, qreal value);
|
void downloadFileProgress(const QString& messageId, qreal value);
|
||||||
|
void uploadFileError(const QString& messageId, const QString& error);
|
||||||
|
void uploadFileProgress(const QString& messageId, qreal value);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start();
|
void start();
|
||||||
@ -76,6 +78,7 @@ public slots:
|
|||||||
void disconnectAccount(const QString& account);
|
void disconnectAccount(const QString& account);
|
||||||
void changeState(int state);
|
void changeState(int state);
|
||||||
void sendMessage(const QString& account, const Shared::Message& data);
|
void sendMessage(const QString& account, const Shared::Message& data);
|
||||||
|
void sendMessage(const QString& account, const Shared::Message& data, const QString& path);
|
||||||
void requestArchive(const QString& account, const QString& jid, int count, const QString& before);
|
void requestArchive(const QString& account, const QString& jid, int count, const QString& before);
|
||||||
void subscribeContact(const QString& account, const QString& jid, const QString& reason);
|
void subscribeContact(const QString& account, const QString& jid, const QString& reason);
|
||||||
void unsubscribeContact(const QString& account, const QString& jid, const QString& reason);
|
void unsubscribeContact(const QString& account, const QString& jid, const QString& reason);
|
||||||
|
@ -73,7 +73,7 @@ void Core::Storage::close()
|
|||||||
void Core::Storage::addRecord(const QString& key, const QString& value)
|
void Core::Storage::addRecord(const QString& key, const QString& value)
|
||||||
{
|
{
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
throw Archive::Closed("addElement", name.toStdString());
|
throw Archive::Closed("addRecord", name.toStdString());
|
||||||
}
|
}
|
||||||
const std::string& id = key.toStdString();
|
const std::string& id = key.toStdString();
|
||||||
const std::string& val = value.toStdString();
|
const std::string& val = value.toStdString();
|
||||||
@ -99,6 +99,33 @@ void Core::Storage::addRecord(const QString& key, const QString& value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::Storage::changeRecord(const QString& key, const QString& value)
|
||||||
|
{
|
||||||
|
if (!opened) {
|
||||||
|
throw Archive::Closed("changeRecord", name.toStdString());
|
||||||
|
}
|
||||||
|
const std::string& id = key.toStdString();
|
||||||
|
const std::string& val = value.toStdString();
|
||||||
|
|
||||||
|
MDB_val lmdbKey, lmdbData;
|
||||||
|
lmdbKey.mv_size = id.size();
|
||||||
|
lmdbKey.mv_data = (char*)id.c_str();
|
||||||
|
lmdbData.mv_size = val.size();
|
||||||
|
lmdbData.mv_data = (char*)val.c_str();
|
||||||
|
MDB_txn *txn;
|
||||||
|
mdb_txn_begin(environment, NULL, 0, &txn);
|
||||||
|
int rc;
|
||||||
|
rc = mdb_put(txn, base, &lmdbKey, &lmdbData, 0);
|
||||||
|
if (rc != 0) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
if (rc) {
|
||||||
|
throw Archive::Unknown(name.toStdString(), mdb_strerror(rc));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mdb_txn_commit(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString Core::Storage::getRecord(const QString& key) const
|
QString Core::Storage::getRecord(const QString& key) const
|
||||||
{
|
{
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
|
@ -39,6 +39,7 @@ public:
|
|||||||
void close();
|
void close();
|
||||||
|
|
||||||
void addRecord(const QString& key, const QString& value);
|
void addRecord(const QString& key, const QString& value);
|
||||||
|
void changeRecord(const QString& key, const QString& value);
|
||||||
void removeRecord(const QString& key);
|
void removeRecord(const QString& key);
|
||||||
QString getRecord(const QString& key) const;
|
QString getRecord(const QString& key) const;
|
||||||
|
|
||||||
|
5
main.cpp
5
main.cpp
@ -70,6 +70,8 @@ int main(int argc, char *argv[])
|
|||||||
QObject::connect(&w, SIGNAL(disconnectAccount(const QString&)), squawk, SLOT(disconnectAccount(const QString&)));
|
QObject::connect(&w, SIGNAL(disconnectAccount(const QString&)), squawk, SLOT(disconnectAccount(const QString&)));
|
||||||
QObject::connect(&w, SIGNAL(changeState(int)), squawk, SLOT(changeState(int)));
|
QObject::connect(&w, SIGNAL(changeState(int)), squawk, SLOT(changeState(int)));
|
||||||
QObject::connect(&w, SIGNAL(sendMessage(const QString&, const Shared::Message&)), squawk, SLOT(sendMessage(const QString&, const Shared::Message&)));
|
QObject::connect(&w, SIGNAL(sendMessage(const QString&, const Shared::Message&)), squawk, SLOT(sendMessage(const QString&, const Shared::Message&)));
|
||||||
|
QObject::connect(&w, SIGNAL(sendMessage(const QString&, const Shared::Message&, const QString&)),
|
||||||
|
squawk, SLOT(sendMessage(const QString&, const Shared::Message&, const QString&)));
|
||||||
QObject::connect(&w, SIGNAL(requestArchive(const QString&, const QString&, int, const QString&)),
|
QObject::connect(&w, SIGNAL(requestArchive(const QString&, const QString&, int, const QString&)),
|
||||||
squawk, SLOT(requestArchive(const QString&, const QString&, int, const QString&)));
|
squawk, SLOT(requestArchive(const QString&, const QString&, int, const QString&)));
|
||||||
QObject::connect(&w, SIGNAL(subscribeContact(const QString&, const QString&, const QString&)),
|
QObject::connect(&w, SIGNAL(subscribeContact(const QString&, const QString&, const QString&)),
|
||||||
@ -125,9 +127,6 @@ int main(int argc, char *argv[])
|
|||||||
QObject::connect(squawk, SIGNAL(downloadFileProgress(const QString&, qreal)), &w, SLOT(downloadFileProgress(const QString&, qreal)));
|
QObject::connect(squawk, SIGNAL(downloadFileProgress(const QString&, qreal)), &w, SLOT(downloadFileProgress(const QString&, qreal)));
|
||||||
QObject::connect(squawk, SIGNAL(downloadFileError(const QString&, const QString&)), &w, SLOT(downloadFileError(const QString&, const QString&)));
|
QObject::connect(squawk, SIGNAL(downloadFileError(const QString&, const QString&)), &w, SLOT(downloadFileError(const QString&, const QString&)));
|
||||||
|
|
||||||
|
|
||||||
//qDebug() << QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
|
|
||||||
|
|
||||||
coreThread->start();
|
coreThread->start();
|
||||||
|
|
||||||
int result = app.exec();
|
int result = app.exec();
|
||||||
|
@ -285,6 +285,7 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
|||||||
|
|
||||||
connect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*)));
|
connect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*)));
|
||||||
connect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&)));
|
connect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&)));
|
||||||
|
connect(conv, SIGNAL(sendMessage(const Shared::Message&, const QString&)), this, SLOT(onConversationMessage(const Shared::Message&, const QString&)));
|
||||||
connect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&)));
|
connect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&)));
|
||||||
connect(conv, SIGNAL(requestLocalFile(const QString&, const QString&)), this, SLOT(onConversationRequestLocalFile(const QString&, const QString&)));
|
connect(conv, SIGNAL(requestLocalFile(const QString&, const QString&)), this, SLOT(onConversationRequestLocalFile(const QString&, const QString&)));
|
||||||
connect(conv, SIGNAL(downloadFile(const QString&, const QString&)), this, SLOT(onConversationDownloadFile(const QString&, const QString&)));
|
connect(conv, SIGNAL(downloadFile(const QString&, const QString&)), this, SLOT(onConversationDownloadFile(const QString&, const QString&)));
|
||||||
@ -468,10 +469,15 @@ void Squawk::notify(const QString& account, const Shared::Message& msg)
|
|||||||
void Squawk::onConversationMessage(const Shared::Message& msg)
|
void Squawk::onConversationMessage(const Shared::Message& msg)
|
||||||
{
|
{
|
||||||
Conversation* conv = static_cast<Conversation*>(sender());
|
Conversation* conv = static_cast<Conversation*>(sender());
|
||||||
|
|
||||||
emit sendMessage(conv->getAccount(), msg);
|
emit sendMessage(conv->getAccount(), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Squawk::onConversationMessage(const Shared::Message& msg, const QString& path)
|
||||||
|
{
|
||||||
|
Conversation* conv = static_cast<Conversation*>(sender());
|
||||||
|
emit sendMessage(conv->getAccount(), msg, path);
|
||||||
|
}
|
||||||
|
|
||||||
void Squawk::onConversationRequestArchive(const QString& before)
|
void Squawk::onConversationRequestArchive(const QString& before)
|
||||||
{
|
{
|
||||||
Conversation* conv = static_cast<Conversation*>(sender());
|
Conversation* conv = static_cast<Conversation*>(sender());
|
||||||
|
@ -57,6 +57,7 @@ signals:
|
|||||||
void disconnectAccount(const QString&);
|
void disconnectAccount(const QString&);
|
||||||
void changeState(int state);
|
void changeState(int state);
|
||||||
void sendMessage(const QString& account, const Shared::Message& data);
|
void sendMessage(const QString& account, const Shared::Message& data);
|
||||||
|
void sendMessage(const QString& account, const Shared::Message& data, const QString& path);
|
||||||
void requestArchive(const QString& account, const QString& jid, int count, const QString& before);
|
void requestArchive(const QString& account, const QString& jid, int count, const QString& before);
|
||||||
void subscribeContact(const QString& account, const QString& jid, const QString& reason);
|
void subscribeContact(const QString& account, const QString& jid, const QString& reason);
|
||||||
void unsubscribeContact(const QString& account, const QString& jid, const QString& reason);
|
void unsubscribeContact(const QString& account, const QString& jid, const QString& reason);
|
||||||
@ -121,6 +122,7 @@ private slots:
|
|||||||
void onComboboxActivated(int index);
|
void onComboboxActivated(int index);
|
||||||
void onRosterItemDoubleClicked(const QModelIndex& item);
|
void onRosterItemDoubleClicked(const QModelIndex& item);
|
||||||
void onConversationMessage(const Shared::Message& msg);
|
void onConversationMessage(const Shared::Message& msg);
|
||||||
|
void onConversationMessage(const Shared::Message& msg, const QString& path);
|
||||||
void onConversationRequestArchive(const QString& before);
|
void onConversationRequestArchive(const QString& before);
|
||||||
void onRosterContextMenu(const QPoint& point);
|
void onRosterContextMenu(const QPoint& point);
|
||||||
void onConversationShown();
|
void onConversationShown();
|
||||||
|
@ -80,6 +80,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sendMessage(const Shared::Message& message);
|
void sendMessage(const Shared::Message& message);
|
||||||
|
void sendMessage(const Shared::Message& message, const QString& path);
|
||||||
void requestArchive(const QString& before);
|
void requestArchive(const QString& before);
|
||||||
void shown();
|
void shown();
|
||||||
void requestLocalFile(const QString& messageId, const QString& url);
|
void requestLocalFile(const QString& messageId, const QString& url);
|
||||||
|
Loading…
Reference in New Issue
Block a user