forked from blue/squawk
First steps on the new idea of file up/downloading
This commit is contained in:
parent
8f914c02a7
commit
3a7735b192
23 changed files with 650 additions and 525 deletions
|
@ -84,8 +84,9 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
|||
QObject::connect(dm, &QXmppDiscoveryManager::itemsReceived, this, &Account::onDiscoveryItemsReceived);
|
||||
QObject::connect(dm, &QXmppDiscoveryManager::infoReceived, this, &Account::onDiscoveryInfoReceived);
|
||||
|
||||
QObject::connect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onFileUploaded);
|
||||
QObject::connect(network, &NetworkAccess::uploadFileError, mh, &MessageHandler::onFileUploadError);
|
||||
QObject::connect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onUploadFileComplete);
|
||||
QObject::connect(network, &NetworkAccess::downloadFileComplete, mh, &MessageHandler::onDownloadFileComplete);
|
||||
QObject::connect(network, &NetworkAccess::loadFileError, mh, &MessageHandler::onLoadFileError);
|
||||
|
||||
client.addExtension(rcpm);
|
||||
QObject::connect(rcpm, &QXmppMessageReceiptManager::messageDelivered, mh, &MessageHandler::onReceiptReceived);
|
||||
|
@ -155,8 +156,9 @@ Account::~Account()
|
|||
reconnectTimer->stop();
|
||||
}
|
||||
|
||||
QObject::disconnect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onFileUploaded);
|
||||
QObject::disconnect(network, &NetworkAccess::uploadFileError, mh, &MessageHandler::onFileUploadError);
|
||||
QObject::disconnect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onUploadFileComplete);
|
||||
QObject::disconnect(network, &NetworkAccess::downloadFileComplete, mh, &MessageHandler::onDownloadFileComplete);
|
||||
QObject::disconnect(network, &NetworkAccess::loadFileError, mh, &MessageHandler::onLoadFileError);
|
||||
|
||||
delete mh;
|
||||
delete rh;
|
||||
|
@ -549,9 +551,11 @@ void Core::Account::onClientError(QXmppClient::Error err)
|
|||
case QXmppStanza::Error::NotAuthorized:
|
||||
errorText = "Authentication error";
|
||||
break;
|
||||
#if (QXMPP_VERSION) < QT_VERSION_CHECK(1, 3, 0)
|
||||
case QXmppStanza::Error::PaymentRequired:
|
||||
errorText = "Payment is required";
|
||||
break;
|
||||
#endif
|
||||
case QXmppStanza::Error::RecipientUnavailable:
|
||||
errorText = "Recipient is unavailable";
|
||||
break;
|
||||
|
|
|
@ -133,7 +133,7 @@ signals:
|
|||
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);
|
||||
void uploadFileError(const QString& messageId, const QString& error);
|
||||
void uploadFileError(const QString& jid, const QString& messageId, const QString& error);
|
||||
|
||||
private:
|
||||
QString name;
|
||||
|
|
|
@ -168,14 +168,16 @@ void Core::MessageHandler::initializeMessage(Shared::Message& target, const QXmp
|
|||
id = source.id();
|
||||
#endif
|
||||
target.setId(id);
|
||||
if (target.getId().size() == 0) {
|
||||
QString messageId = target.getId();
|
||||
if (messageId.size() == 0) {
|
||||
target.generateRandomId(); //TODO out of desperation, I need at least a random ID
|
||||
messageId = target.getId();
|
||||
}
|
||||
target.setFrom(source.from());
|
||||
target.setTo(source.to());
|
||||
target.setBody(source.body());
|
||||
target.setForwarded(forwarded);
|
||||
target.setOutOfBandUrl(source.outOfBandUrl());
|
||||
|
||||
if (guessing) {
|
||||
if (target.getFromJid() == acc->getLogin() + "@" + acc->getServer()) {
|
||||
outgoing = true;
|
||||
|
@ -189,6 +191,12 @@ void Core::MessageHandler::initializeMessage(Shared::Message& target, const QXmp
|
|||
} else {
|
||||
target.setCurrentTime();
|
||||
}
|
||||
|
||||
QString oob = source.outOfBandUrl();
|
||||
if (oob.size() > 0) {
|
||||
target.setAttachPath(acc->network->addMessageAndCheckForPath(oob, acc->getName(), target.getPenPalJid(), messageId));
|
||||
}
|
||||
target.setOutOfBandUrl(oob);
|
||||
}
|
||||
|
||||
void Core::MessageHandler::logMessage(const QXmppMessage& msg, const QString& reason)
|
||||
|
@ -292,7 +300,7 @@ void Core::MessageHandler::prepareUpload(const Shared::Message& data)
|
|||
if (url.size() != 0) {
|
||||
sendMessageWithLocalUploadedFile(data, url);
|
||||
} else {
|
||||
if (acc->network->isUploading(path, data.getId())) {
|
||||
if (acc->network->checkAndAddToUploading(acc->getName(), data.getPenPalJid(), data.getId(), path)) {
|
||||
pendingMessages.emplace(data.getId(), data);
|
||||
} else {
|
||||
if (acc->um->serviceFound()) {
|
||||
|
@ -303,17 +311,17 @@ void Core::MessageHandler::prepareUpload(const Shared::Message& data)
|
|||
acc->um->requestUploadSlot(file);
|
||||
}
|
||||
} else {
|
||||
onFileUploadError(data.getId(), "Uploading file no longer exists or your system user has no permission to read it");
|
||||
handleUploadError(data.getPenPalJid(), data.getId(), "Uploading file no longer exists or your system user has no permission to read it");
|
||||
qDebug() << "Requested upload slot in account" << acc->name << "for file" << path << "but the file doesn't exist or is not readable";
|
||||
}
|
||||
} else {
|
||||
onFileUploadError(data.getId(), "Your server doesn't support file upload service, or it's prohibited for your account");
|
||||
handleUploadError(data.getPenPalJid(), data.getId(), "Your server doesn't support file upload service, or it's prohibited for your account");
|
||||
qDebug() << "Requested upload slot in account" << acc->name << "for file" << path << "but upload manager didn't discover any upload services";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
onFileUploadError(data.getId(), "Account is offline or reconnecting");
|
||||
handleUploadError(data.getPenPalJid(), data.getId(), "Account is offline or reconnecting");
|
||||
qDebug() << "An attempt to send message with not connected account " << acc->name << ", skipping";
|
||||
}
|
||||
}
|
||||
|
@ -326,10 +334,10 @@ void Core::MessageHandler::onUploadSlotReceived(const QXmppHttpUploadSlotIq& slo
|
|||
} else {
|
||||
const std::pair<QString, Shared::Message>& pair = uploadingSlotsQueue.front();
|
||||
const QString& mId = pair.second.getId();
|
||||
acc->network->uploadFile(mId, pair.first, slot.putUrl(), slot.getUrl(), slot.putHeaders());
|
||||
acc->network->uploadFile({acc->name, pair.second.getPenPalJid(), mId}, pair.first, slot.putUrl(), slot.getUrl(), slot.putHeaders());
|
||||
pendingMessages.emplace(mId, pair.second);
|
||||
uploadingSlotsQueue.pop_front();
|
||||
|
||||
uploadingSlotsQueue.pop_front();
|
||||
if (uploadingSlotsQueue.size() > 0) {
|
||||
acc->um->requestUploadSlot(uploadingSlotsQueue.front().first);
|
||||
}
|
||||
|
@ -338,35 +346,69 @@ void Core::MessageHandler::onUploadSlotReceived(const QXmppHttpUploadSlotIq& slo
|
|||
|
||||
void Core::MessageHandler::onUploadSlotRequestFailed(const QXmppHttpUploadRequestIq& request)
|
||||
{
|
||||
QString err(request.error().text());
|
||||
if (uploadingSlotsQueue.size() == 0) {
|
||||
qDebug() << "HTTP Upload manager of account" << acc->name << "reports about an error requesting upload slot, but none was requested";
|
||||
qDebug() << request.error().text();
|
||||
qDebug() << err;
|
||||
} else {
|
||||
const std::pair<QString, Shared::Message>& pair = uploadingSlotsQueue.front();
|
||||
qDebug() << "Error requesting upload slot for file" << pair.first << "in account" << acc->name << ":" << request.error().text();
|
||||
emit acc->uploadFileError(pair.second.getId(), "Error requesting slot to upload file: " + request.error().text());
|
||||
qDebug() << "Error requesting upload slot for file" << pair.first << "in account" << acc->name << ":" << err;
|
||||
emit acc->uploadFileError(pair.second.getPenPalJid(), pair.second.getId(), "Error requesting slot to upload file: " + err);
|
||||
|
||||
uploadingSlotsQueue.pop_front();
|
||||
if (uploadingSlotsQueue.size() > 0) {
|
||||
acc->um->requestUploadSlot(uploadingSlotsQueue.front().first);
|
||||
}
|
||||
uploadingSlotsQueue.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void Core::MessageHandler::onFileUploaded(const QString& messageId, const QString& url)
|
||||
void Core::MessageHandler::onDownloadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& path)
|
||||
{
|
||||
std::map<QString, Shared::Message>::const_iterator itr = pendingMessages.find(messageId);
|
||||
if (itr != pendingMessages.end()) {
|
||||
sendMessageWithLocalUploadedFile(itr->second, url);
|
||||
pendingMessages.erase(itr);
|
||||
QMap<QString, QVariant> cData = {
|
||||
{"attachPath", path}
|
||||
};
|
||||
for (const Shared::MessageInfo& info : msgs) {
|
||||
if (info.account == acc->getName()) {
|
||||
Contact* cnt = acc->rh->getContact(info.jid);
|
||||
if (cnt != 0) {
|
||||
if (cnt->changeMessage(info.messageId, cData)) {
|
||||
emit acc->changeMessage(info.jid, info.messageId, cData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::MessageHandler::onFileUploadError(const QString& messageId, const QString& errMsg)
|
||||
void Core::MessageHandler::onLoadFileError(const std::list<Shared::MessageInfo>& msgs, const QString& text, bool up)
|
||||
{
|
||||
if (up) {
|
||||
for (const Shared::MessageInfo& info : msgs) {
|
||||
if (info.account == acc->getName()) {
|
||||
handleUploadError(info.jid, info.messageId, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::MessageHandler::handleUploadError(const QString& jid, const QString& messageId, const QString& errorText)
|
||||
{
|
||||
std::map<QString, Shared::Message>::const_iterator itr = pendingMessages.find(messageId);
|
||||
if (itr != pendingMessages.end()) {
|
||||
pendingMessages.erase(itr);
|
||||
//TODO move the storage of pending messages to the database and change them there
|
||||
}
|
||||
}
|
||||
|
||||
void Core::MessageHandler::onUploadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& path)
|
||||
{
|
||||
for (const Shared::MessageInfo& info : msgs) {
|
||||
if (info.account == acc->getName()) {
|
||||
std::map<QString, Shared::Message>::const_iterator itr = pendingMessages.find(info.messageId);
|
||||
if (itr != pendingMessages.end()) {
|
||||
sendMessageWithLocalUploadedFile(itr->second, path);
|
||||
pendingMessages.erase(itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <QXmppHttpUploadIq.h>
|
||||
|
||||
#include <shared/message.h>
|
||||
#include <shared/messageinfo.h>
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
@ -54,8 +55,9 @@ public slots:
|
|||
void onReceiptReceived(const QString& jid, const QString& id);
|
||||
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& errMsg);
|
||||
void onDownloadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& path);
|
||||
void onUploadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& path);
|
||||
void onLoadFileError(const std::list<Shared::MessageInfo>& msgs, const QString& path, bool up);
|
||||
|
||||
private:
|
||||
bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false);
|
||||
|
@ -64,6 +66,7 @@ private:
|
|||
void sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url);
|
||||
void performSending(Shared::Message data);
|
||||
void prepareUpload(const Shared::Message& data);
|
||||
void handleUploadError(const QString& jid, const QString& messageId, const QString& errorText);
|
||||
|
||||
private:
|
||||
Account* acc;
|
||||
|
|
|
@ -16,13 +16,17 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
#include "networkaccess.h"
|
||||
|
||||
Core::NetworkAccess::NetworkAccess(QObject* parent):
|
||||
QObject(parent),
|
||||
running(false),
|
||||
manager(0),
|
||||
files("files"),
|
||||
storage("fileURLStorage"),
|
||||
downloads(),
|
||||
uploads()
|
||||
{
|
||||
|
@ -33,60 +37,31 @@ Core::NetworkAccess::~NetworkAccess()
|
|||
stop();
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::fileLocalPathRequest(const QString& messageId, const QString& url)
|
||||
void Core::NetworkAccess::downladFile(const QString& url)
|
||||
{
|
||||
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
||||
if (itr != downloads.end()) {
|
||||
Transfer* dwn = itr->second;
|
||||
std::set<QString>::const_iterator mItr = dwn->messages.find(messageId);
|
||||
if (mItr == dwn->messages.end()) {
|
||||
dwn->messages.insert(messageId);
|
||||
}
|
||||
emit downloadFileProgress(messageId, dwn->progress);
|
||||
qDebug() << "NetworkAccess received a request to download a file" << url << ", but the file is currently downloading, skipping";
|
||||
} else {
|
||||
try {
|
||||
QString path = files.getRecord(url);
|
||||
QFileInfo info(path);
|
||||
if (info.exists() && info.isFile()) {
|
||||
emit fileLocalPathResponse(messageId, path);
|
||||
std::pair<QString, std::list<Shared::MessageInfo>> p = storage.getPath(url);
|
||||
if (p.first.size() > 0) {
|
||||
QFileInfo info(p.first);
|
||||
if (info.exists() && info.isFile()) {
|
||||
emit downloadFileComplete(p.second, p.first);
|
||||
} else {
|
||||
startDownload(p.second, url);
|
||||
}
|
||||
} else {
|
||||
files.removeRecord(url);
|
||||
emit fileLocalPathResponse(messageId, "");
|
||||
startDownload(p.second, url);
|
||||
}
|
||||
} catch (const Archive::NotFound& e) {
|
||||
emit fileLocalPathResponse(messageId, "");
|
||||
qDebug() << "NetworkAccess received a request to download a file" << url << ", but there is now record of which message uses that file, downloading anyway";
|
||||
storage.addFile(url);
|
||||
startDownload(std::list<Shared::MessageInfo>(), url);
|
||||
} catch (const Archive::Unknown& e) {
|
||||
qDebug() << "Error requesting file path:" << e.what();
|
||||
emit fileLocalPathResponse(messageId, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::downladFileRequest(const QString& messageId, const QString& url)
|
||||
{
|
||||
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
||||
if (itr != downloads.end()) {
|
||||
Transfer* dwn = itr->second;
|
||||
std::set<QString>::const_iterator mItr = dwn->messages.find(messageId);
|
||||
if (mItr == dwn->messages.end()) {
|
||||
dwn->messages.insert(messageId);
|
||||
}
|
||||
emit downloadFileProgress(messageId, dwn->progress);
|
||||
} else {
|
||||
try {
|
||||
QString path = files.getRecord(url);
|
||||
QFileInfo info(path);
|
||||
if (info.exists() && info.isFile()) {
|
||||
emit fileLocalPathResponse(messageId, path);
|
||||
} else {
|
||||
files.removeRecord(url);
|
||||
startDownload(messageId, url);
|
||||
}
|
||||
} catch (const Archive::NotFound& e) {
|
||||
startDownload(messageId, url);
|
||||
} catch (const Archive::Unknown& e) {
|
||||
qDebug() << "Error requesting file path:" << e.what();
|
||||
emit downloadFileError(messageId, QString("Database error: ") + e.what());
|
||||
emit loadFileError(std::list<Shared::MessageInfo>(), QString("Database error: ") + e.what(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +70,7 @@ void Core::NetworkAccess::start()
|
|||
{
|
||||
if (!running) {
|
||||
manager = new QNetworkAccessManager();
|
||||
files.open();
|
||||
storage.open();
|
||||
running = true;
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +78,7 @@ void Core::NetworkAccess::start()
|
|||
void Core::NetworkAccess::stop()
|
||||
{
|
||||
if (running) {
|
||||
files.close();
|
||||
storage.close();
|
||||
manager->deleteLater();
|
||||
manager = 0;
|
||||
running = false;
|
||||
|
@ -128,9 +103,7 @@ void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesT
|
|||
qreal total = bytesTotal;
|
||||
qreal progress = received/total;
|
||||
dwn->progress = progress;
|
||||
for (std::set<QString>::const_iterator mItr = dwn->messages.begin(), end = dwn->messages.end(); mItr != end; ++mItr) {
|
||||
emit downloadFileProgress(*mItr, progress);
|
||||
}
|
||||
emit loadFileProgress(dwn->messages, progress, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,9 +119,7 @@ void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code)
|
|||
if (errorText.size() > 0) {
|
||||
itr->second->success = false;
|
||||
Transfer* dwn = itr->second;
|
||||
for (std::set<QString>::const_iterator mItr = dwn->messages.begin(), end = dwn->messages.end(); mItr != end; ++mItr) {
|
||||
emit downloadFileError(*mItr, errorText);
|
||||
}
|
||||
emit loadFileError(dwn->messages, errorText, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -276,61 +247,54 @@ QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code)
|
|||
|
||||
void Core::NetworkAccess::onDownloadFinished()
|
||||
{
|
||||
QString path("");
|
||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||
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 done but seems like noone is waiting for it, skipping";
|
||||
qDebug() << "an error downloading" << url << ": the request is done but there is no record of it being downloaded, ignoring";
|
||||
} else {
|
||||
Transfer* dwn = itr->second;
|
||||
if (dwn->success) {
|
||||
qDebug() << "download success for" << url;
|
||||
QStringList hops = url.split("/");
|
||||
QString fileName = hops.back();
|
||||
QStringList parts = fileName.split(".");
|
||||
path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + "/";
|
||||
QString suffix("");
|
||||
QStringList::const_iterator sItr = parts.begin();
|
||||
QString realName = *sItr;
|
||||
++sItr;
|
||||
for (QStringList::const_iterator sEnd = parts.end(); sItr != sEnd; ++sItr) {
|
||||
suffix += "." + (*sItr);
|
||||
QString jid;
|
||||
if (dwn->messages.size() > 0) {
|
||||
jid = dwn->messages.front().jid;
|
||||
}
|
||||
QString postfix("");
|
||||
QFileInfo proposedName(path + realName + postfix + suffix);
|
||||
int counter = 0;
|
||||
while (proposedName.exists()) {
|
||||
postfix = QString("(") + std::to_string(++counter).c_str() + ")";
|
||||
proposedName = QFileInfo(path + realName + postfix + suffix);
|
||||
QString path = prepareDirectory(jid);
|
||||
if (path.size() > 0) {
|
||||
path = checkFileName(fileName, path);
|
||||
|
||||
QFile file(path);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(dwn->reply->readAll());
|
||||
file.close();
|
||||
storage.setPath(url, path);
|
||||
qDebug() << "file" << path << "was successfully downloaded";
|
||||
} else {
|
||||
qDebug() << "couldn't save file" << path;
|
||||
path = QString();
|
||||
}
|
||||
}
|
||||
|
||||
path = proposedName.absoluteFilePath();
|
||||
QFile file(path);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(dwn->reply->readAll());
|
||||
file.close();
|
||||
files.addRecord(url, path);
|
||||
qDebug() << "file" << path << "was successfully downloaded";
|
||||
if (path.size() > 0) {
|
||||
emit downloadFileComplete(dwn->messages, path);
|
||||
} else {
|
||||
qDebug() << "couldn't save file" << path;
|
||||
path = "";
|
||||
//TODO do I need to handle the failure here or it's already being handled in error?
|
||||
//emit loadFileError(dwn->messages, path, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<QString>::const_iterator mItr = dwn->messages.begin(), end = dwn->messages.end(); mItr != end; ++mItr) {
|
||||
emit fileLocalPathResponse(*mItr, path);
|
||||
}
|
||||
|
||||
dwn->reply->deleteLater();
|
||||
delete dwn;
|
||||
downloads.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::startDownload(const QString& messageId, const QString& url)
|
||||
void Core::NetworkAccess::startDownload(const std::list<Shared::MessageInfo>& msgs, const QString& url)
|
||||
{
|
||||
Transfer* dwn = new Transfer({{messageId}, 0, 0, true, "", url, 0});
|
||||
Transfer* dwn = new Transfer({msgs, 0, 0, true, "", url, 0});
|
||||
QNetworkRequest req(url);
|
||||
dwn->reply = manager->get(req);
|
||||
connect(dwn->reply, &QNetworkReply::downloadProgress, this, &NetworkAccess::onDownloadProgress);
|
||||
|
@ -341,7 +305,7 @@ void Core::NetworkAccess::startDownload(const QString& messageId, const QString&
|
|||
#endif
|
||||
connect(dwn->reply, &QNetworkReply::finished, this, &NetworkAccess::onDownloadFinished);
|
||||
downloads.insert(std::make_pair(url, dwn));
|
||||
emit downloadFileProgress(messageId, 0);
|
||||
emit loadFileProgress(dwn->messages, 0, false);
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code)
|
||||
|
@ -350,16 +314,16 @@ void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code)
|
|||
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";
|
||||
qDebug() << "an error uploading" << url << ": the request is reporting an error but there is no record of it being uploading, ignoring";
|
||||
} 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);
|
||||
}
|
||||
emit loadFileError(upl->messages, errorText, true);
|
||||
}
|
||||
|
||||
//TODO deletion?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,17 +333,14 @@ 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 no one is waiting for it, skipping";
|
||||
qDebug() << "an error uploading" << url << ": the request is done there is no record of it being uploading, ignoring";
|
||||
} else {
|
||||
Transfer* upl = itr->second;
|
||||
if (upl->success) {
|
||||
qDebug() << "upload success for" << url;
|
||||
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);
|
||||
}
|
||||
|
||||
storage.addFile(upl->messages, upl->url, upl->path);
|
||||
emit uploadFileComplete(upl->messages, upl->url);
|
||||
}
|
||||
|
||||
upl->reply->deleteLater();
|
||||
|
@ -403,94 +364,29 @@ void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTot
|
|||
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, url, 0});
|
||||
QNetworkRequest req(url);
|
||||
QFile* file = new QFile(path);
|
||||
if (file->open(QIODevice::ReadOnly)) {
|
||||
upl->reply = manager->put(req, file);
|
||||
|
||||
connect(upl->reply, &QNetworkReply::uploadProgress, this, &NetworkAccess::onUploadProgress);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::errorOccurred), this, &NetworkAccess::onUploadError);
|
||||
#else
|
||||
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this, &NetworkAccess::onUploadError);
|
||||
#endif
|
||||
|
||||
connect(upl->reply, &QNetworkReply::finished, this, &NetworkAccess::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) {
|
||||
QFileInfo info(path);
|
||||
if (info.exists() && info.isFile()) {
|
||||
emit fileLocalPathResponse(messageId, path);
|
||||
} else {
|
||||
files.removeRecord(url);
|
||||
startUpload(messageId, url, path);
|
||||
}
|
||||
} else {
|
||||
QFileInfo info(path);
|
||||
if (info.exists() && info.isFile()) {
|
||||
files.changeRecord(url, path);
|
||||
emit fileLocalPathResponse(messageId, path);
|
||||
} else {
|
||||
files.removeRecord(url);
|
||||
startUpload(messageId, url, path);
|
||||
}
|
||||
}
|
||||
} catch (const Archive::NotFound& e) {
|
||||
startUpload(messageId, url, path);
|
||||
} catch (const Archive::Unknown& e) {
|
||||
qDebug() << "Error requesting file path on upload:" << e.what();
|
||||
emit uploadFileError(messageId, QString("Database error: ") + e.what());
|
||||
}
|
||||
emit loadFileProgress(upl->messages, progress, true);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
QString p;
|
||||
|
||||
try {
|
||||
QString p = storage.getUrl(path);
|
||||
} catch (const Archive::NotFound& err) {
|
||||
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
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)
|
||||
void Core::NetworkAccess::uploadFile(const Shared::MessageInfo& info, const QString& path, const QUrl& put, const QUrl& get, const QMap<QString, QString> headers)
|
||||
{
|
||||
QFile* file = new QFile(path);
|
||||
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, get.toString(), file});
|
||||
Transfer* upl = new Transfer({{info}, 0, 0, true, path, get.toString(), file});
|
||||
QNetworkRequest req(put);
|
||||
for (QMap<QString, QString>::const_iterator itr = headers.begin(), end = headers.end(); itr != end; itr++) {
|
||||
req.setRawHeader(itr.key().toUtf8(), itr.value().toUtf8());
|
||||
|
@ -506,10 +402,94 @@ void Core::NetworkAccess::uploadFile(const QString& messageId, const QString& pa
|
|||
#endif
|
||||
connect(upl->reply, &QNetworkReply::finished, this, &NetworkAccess::onUploadFinished);
|
||||
uploads.insert(std::make_pair(put.toString(), upl));
|
||||
emit downloadFileProgress(messageId, 0);
|
||||
emit loadFileProgress(upl->messages, 0, true);
|
||||
} else {
|
||||
qDebug() << "couldn't upload file" << path;
|
||||
emit uploadFileError(messageId, "Error opening file");
|
||||
emit loadFileError(upl->messages, "Error opening file", true);
|
||||
delete file;
|
||||
delete upl;
|
||||
}
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::registerFile(const QString& url, const QString& account, const QString& jid, const QString& id)
|
||||
{
|
||||
storage.addFile(url, account, jid, id);
|
||||
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
||||
if (itr != downloads.end()) {
|
||||
itr->second->messages.emplace_back(account, jid, id); //TODO notification is going to happen the next tick, is that okay?
|
||||
}
|
||||
}
|
||||
|
||||
void Core::NetworkAccess::registerFile(const QString& url, const QString& path, const QString& account, const QString& jid, const QString& id)
|
||||
{
|
||||
storage.addFile(url, path, account, jid, id);
|
||||
}
|
||||
|
||||
bool Core::NetworkAccess::checkAndAddToUploading(const QString& acc, const QString& jid, const QString id, const QString path)
|
||||
{
|
||||
for (const std::pair<const QString, Transfer*>& pair : uploads) {
|
||||
Transfer* info = pair.second;
|
||||
if (pair.second->path == path) {
|
||||
std::list<Shared::MessageInfo>& messages = info->messages;
|
||||
bool dup = false;
|
||||
for (const Shared::MessageInfo& info : messages) {
|
||||
if (info.account == acc && info.jid == jid && info.messageId == id) {
|
||||
dup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dup) {
|
||||
info->messages.emplace_back(acc, jid, id); //TODO notification is going to happen the next tick, is that okay?
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString Core::NetworkAccess::prepareDirectory(const QString& jid)
|
||||
{
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
path += "/" + QApplication::applicationName();
|
||||
if (jid.size() > 0) {
|
||||
path += "/" + jid;
|
||||
}
|
||||
QDir location(path);
|
||||
|
||||
if (!location.exists()) {
|
||||
bool res = location.mkpath(path);
|
||||
if (!res) {
|
||||
return "";
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
QString Core::NetworkAccess::checkFileName(const QString& name, const QString& path)
|
||||
{
|
||||
QStringList parts = name.split(".");
|
||||
QString suffix("");
|
||||
QStringList::const_iterator sItr = parts.begin();
|
||||
QString realName = *sItr;
|
||||
++sItr;
|
||||
for (QStringList::const_iterator sEnd = parts.end(); sItr != sEnd; ++sItr) {
|
||||
suffix += "." + (*sItr);
|
||||
}
|
||||
QString postfix("");
|
||||
QFileInfo proposedName(path + realName + suffix);
|
||||
int counter = 0;
|
||||
while (proposedName.exists()) {
|
||||
QString count = QString("(") + std::to_string(++counter).c_str() + ")";
|
||||
proposedName = QFileInfo(path + realName + count + suffix);
|
||||
}
|
||||
|
||||
return proposedName.absoluteFilePath();
|
||||
}
|
||||
|
||||
QString Core::NetworkAccess::addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id)
|
||||
{
|
||||
return storage.addMessageAndCheckForPath(url, account, jid, id);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ namespace Core {
|
|||
/**
|
||||
* @todo write docs
|
||||
*/
|
||||
|
||||
//TODO Need to describe how to get rid of records when file is no longer reachable;
|
||||
class NetworkAccess : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -48,26 +50,26 @@ public:
|
|||
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);
|
||||
QString addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id);
|
||||
void uploadFile(const Shared::MessageInfo& info, const QString& path, const QUrl& put, const QUrl& get, const QMap<QString, QString> headers);
|
||||
bool checkAndAddToUploading(const QString& acc, const QString& jid, const QString id, const QString path);
|
||||
|
||||
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);
|
||||
void loadFileProgress(const std::list<Shared::MessageInfo>& msgs, qreal value, bool up);
|
||||
void loadFileError(const std::list<Shared::MessageInfo>& msgs, const QString& text, bool up);
|
||||
void uploadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& url);
|
||||
void downloadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& path);
|
||||
|
||||
public slots:
|
||||
void fileLocalPathRequest(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);
|
||||
void downladFile(const QString& url);
|
||||
void registerFile(const QString& url, const QString& account, const QString& jid, const QString& id);
|
||||
void registerFile(const QString& url, const QString& path, const QString& account, const QString& jid, const QString& id);
|
||||
|
||||
private:
|
||||
void startDownload(const QString& messageId, const QString& url);
|
||||
void startUpload(const QString& messageId, const QString& url, const QString& path);
|
||||
void startDownload(const std::list<Shared::MessageInfo>& msgs, const QString& url);
|
||||
QString getErrorText(QNetworkReply::NetworkError code);
|
||||
QString prepareDirectory(const QString& jid);
|
||||
QString checkFileName(const QString& name, const QString& path);
|
||||
|
||||
private slots:
|
||||
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
|
@ -85,7 +87,7 @@ private:
|
|||
std::map<QString, Transfer*> uploads;
|
||||
|
||||
struct Transfer {
|
||||
std::set<QString> messages;
|
||||
std::list<Shared::MessageInfo> messages;
|
||||
qreal progress;
|
||||
QNetworkReply* reply;
|
||||
bool success;
|
||||
|
|
|
@ -32,11 +32,10 @@ Core::Squawk::Squawk(QObject* parent):
|
|||
,kwallet()
|
||||
#endif
|
||||
{
|
||||
connect(&network, &NetworkAccess::fileLocalPathResponse, this, &Squawk::onNetworkAccessfileLocalPathResponse);
|
||||
connect(&network, &NetworkAccess::downloadFileProgress, this, &Squawk::downloadFileProgress);
|
||||
connect(&network, &NetworkAccess::downloadFileError, this, &Squawk::downloadFileError);
|
||||
connect(&network, &NetworkAccess::uploadFileProgress, this, &Squawk::uploadFileProgress);
|
||||
connect(&network, &NetworkAccess::uploadFileError, this, &Squawk::uploadFileError);
|
||||
connect(&network, &NetworkAccess::loadFileProgress, this, &Squawk::fileProgress);
|
||||
connect(&network, &NetworkAccess::loadFileError, this, &Squawk::fileError);
|
||||
connect(&network, &NetworkAccess::downloadFileComplete, this, &Squawk::fileDownloadComplete);
|
||||
connect(&network, &NetworkAccess::uploadFileComplete, this, &Squawk::fileUploadComplete);
|
||||
|
||||
#ifdef WITH_KWALLET
|
||||
if (kwallet.supportState() == PSE::KWallet::success) {
|
||||
|
@ -168,7 +167,7 @@ void Core::Squawk::addAccount(
|
|||
|
||||
connect(acc, &Account::receivedVCard, this, &Squawk::responseVCard);
|
||||
|
||||
connect(acc, &Account::uploadFileError, this, &Squawk::uploadFileError);
|
||||
connect(acc, &Account::uploadFileError, this, &Squawk::onAccountUploadFileError);
|
||||
|
||||
QMap<QString, QVariant> map = {
|
||||
{"login", login},
|
||||
|
@ -593,14 +592,9 @@ void Core::Squawk::addRoomRequest(const QString& account, const QString& jid, co
|
|||
itr->second->addRoomRequest(jid, nick, password, autoJoin);
|
||||
}
|
||||
|
||||
void Core::Squawk::fileLocalPathRequest(const QString& messageId, const QString& url)
|
||||
void Core::Squawk::fileDownloadRequest(const QString& url)
|
||||
{
|
||||
network.fileLocalPathRequest(messageId, url);
|
||||
}
|
||||
|
||||
void Core::Squawk::downloadFileRequest(const QString& messageId, const QString& url)
|
||||
{
|
||||
network.downladFileRequest(messageId, url);
|
||||
network.downladFile(url);
|
||||
}
|
||||
|
||||
void Core::Squawk::addContactToGroupRequest(const QString& account, const QString& jid, const QString& groupName)
|
||||
|
@ -752,7 +746,8 @@ void Core::Squawk::onWalletResponsePassword(const QString& login, const QString&
|
|||
accountReady();
|
||||
}
|
||||
|
||||
void Core::Squawk::onNetworkAccessfileLocalPathResponse(const QString& messageId, const QString& path)
|
||||
void Core::Squawk::onAccountUploadFileError(const QString& jid, const QString id, const QString& errorText)
|
||||
{
|
||||
|
||||
Account* acc = static_cast<Account*>(sender());
|
||||
emit fileError({{acc->getName(), jid, id}}, errorText, true);
|
||||
}
|
||||
|
|
|
@ -51,30 +51,39 @@ public:
|
|||
signals:
|
||||
void quit();
|
||||
void ready();
|
||||
|
||||
void newAccount(const QMap<QString, QVariant>&);
|
||||
void changeAccount(const QString& account, const QMap<QString, QVariant>& data);
|
||||
void removeAccount(const QString& account);
|
||||
|
||||
void addGroup(const QString& account, const QString& name);
|
||||
void removeGroup(const QString& account, const QString& name);
|
||||
|
||||
void addContact(const QString& account, const QString& jid, const QString& group, const QMap<QString, QVariant>& data);
|
||||
void removeContact(const QString& account, const QString& jid);
|
||||
void removeContact(const QString& account, const QString& jid, const QString& group);
|
||||
void changeContact(const QString& account, const QString& jid, const QMap<QString, QVariant>& data);
|
||||
|
||||
void addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||
void removePresence(const QString& account, const QString& jid, const QString& name);
|
||||
|
||||
void stateChanged(Shared::Availability state);
|
||||
|
||||
void accountMessage(const QString& account, const Shared::Message& data);
|
||||
void responseArchive(const QString& account, const QString& jid, const std::list<Shared::Message>& list, bool last);
|
||||
|
||||
void addRoom(const QString& account, const QString jid, const QMap<QString, QVariant>& data);
|
||||
void changeRoom(const QString& account, const QString jid, const QMap<QString, QVariant>& data);
|
||||
void removeRoom(const QString& account, const QString jid);
|
||||
void addRoomParticipant(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||
void changeRoomParticipant(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||
void removeRoomParticipant(const QString& account, const QString& jid, const QString& name);
|
||||
void downloadFileError(const QString& messageId, const QString& error);
|
||||
void downloadFileProgress(const QString& messageId, qreal value);
|
||||
void uploadFileError(const QString& messageId, const QString& error);
|
||||
void uploadFileProgress(const QString& messageId, qreal value);
|
||||
|
||||
void fileError(const std::list<Shared::MessageInfo> msgs, const QString& error, bool up);
|
||||
void fileProgress(const std::list<Shared::MessageInfo> msgs, qreal value, bool up);
|
||||
void fileDownloadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path);
|
||||
void fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path);
|
||||
|
||||
void responseVCard(const QString& jid, const Shared::VCard& card);
|
||||
void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
|
||||
void requestPassword(const QString& account);
|
||||
|
@ -82,14 +91,18 @@ signals:
|
|||
public slots:
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void newAccountRequest(const QMap<QString, QVariant>& map);
|
||||
void modifyAccountRequest(const QString& name, const QMap<QString, QVariant>& map);
|
||||
void removeAccountRequest(const QString& name);
|
||||
void connectAccount(const QString& account);
|
||||
void disconnectAccount(const QString& account);
|
||||
|
||||
void changeState(Shared::Availability state);
|
||||
|
||||
void sendMessage(const QString& account, const Shared::Message& data);
|
||||
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 unsubscribeContact(const QString& account, const QString& jid, const QString& reason);
|
||||
void addContactToGroupRequest(const QString& account, const QString& jid, const QString& groupName);
|
||||
|
@ -97,12 +110,14 @@ public slots:
|
|||
void removeContactRequest(const QString& account, const QString& jid);
|
||||
void renameContactRequest(const QString& account, const QString& jid, const QString& newName);
|
||||
void addContactRequest(const QString& account, const QString& jid, const QString& name, const QSet<QString>& groups);
|
||||
|
||||
void setRoomJoined(const QString& account, const QString& jid, bool joined);
|
||||
void setRoomAutoJoin(const QString& account, const QString& jid, bool joined);
|
||||
void addRoomRequest(const QString& account, const QString& jid, const QString& nick, const QString& password, bool autoJoin);
|
||||
void removeRoomRequest(const QString& account, const QString& jid);
|
||||
void fileLocalPathRequest(const QString& messageId, const QString& url);
|
||||
void downloadFileRequest(const QString& messageId, const QString& url);
|
||||
|
||||
void fileDownloadRequest(const QString& url);
|
||||
|
||||
void requestVCard(const QString& account, const QString& jid);
|
||||
void uploadVCard(const QString& account, const Shared::VCard& card);
|
||||
void responsePassword(const QString& account, const QString& password);
|
||||
|
@ -153,12 +168,12 @@ private slots:
|
|||
void onAccountRemoveRoomPresence(const QString& jid, const QString& nick);
|
||||
void onAccountChangeMessage(const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
|
||||
|
||||
void onAccountUploadFileError(const QString& jid, const QString id, const QString& errorText);
|
||||
|
||||
void onWalletOpened(bool success);
|
||||
void onWalletResponsePassword(const QString& login, const QString& password);
|
||||
void onWalletRejectPassword(const QString& login);
|
||||
|
||||
void onNetworkAccessfileLocalPathResponse(const QString& messageId, const QString& path);
|
||||
|
||||
private:
|
||||
void readSettings();
|
||||
void accountReady();
|
||||
|
|
|
@ -165,8 +165,7 @@ void Core::UrlStorage::addFile(const QString& url)
|
|||
throw Archive::Closed("addFile(no message, no path)", name.toStdString());
|
||||
}
|
||||
|
||||
UrlInfo info;
|
||||
writeInfo(url, info);
|
||||
addToInfo(url, "", "", "");
|
||||
}
|
||||
|
||||
void Core::UrlStorage::addFile(const QString& url, const QString& path)
|
||||
|
@ -175,8 +174,7 @@ void Core::UrlStorage::addFile(const QString& url, const QString& path)
|
|||
throw Archive::Closed("addFile(no message, with path)", name.toStdString());
|
||||
}
|
||||
|
||||
UrlInfo info(path);
|
||||
writeInfo(url, info);
|
||||
addToInfo(url, "", "", "", path);
|
||||
}
|
||||
|
||||
void Core::UrlStorage::addFile(const QString& url, const QString& account, const QString& jid, const QString& id)
|
||||
|
@ -185,9 +183,7 @@ void Core::UrlStorage::addFile(const QString& url, const QString& account, const
|
|||
throw Archive::Closed("addFile(with message, no path)", name.toStdString());
|
||||
}
|
||||
|
||||
UrlInfo info;
|
||||
info.addMessage(account, jid, id);
|
||||
writeInfo(url, info);
|
||||
addToInfo(url, account, jid, id);
|
||||
}
|
||||
|
||||
void Core::UrlStorage::addFile(const QString& url, const QString& path, const QString& account, const QString& jid, const QString& id)
|
||||
|
@ -196,50 +192,74 @@ void Core::UrlStorage::addFile(const QString& url, const QString& path, const QS
|
|||
throw Archive::Closed("addFile(with message, with path)", name.toStdString());
|
||||
}
|
||||
|
||||
UrlInfo info(path);
|
||||
info.addMessage(account, jid, id);
|
||||
writeInfo(url, info);
|
||||
addToInfo(url, account, jid, id, path);
|
||||
}
|
||||
|
||||
void Core::UrlStorage::addFile(const std::list<Shared::MessageInfo>& msgs, const QString& url, const QString& path)
|
||||
{
|
||||
if (!opened) {
|
||||
throw Archive::Closed("addFile(with list)", name.toStdString());
|
||||
}
|
||||
|
||||
UrlInfo info (path, msgs);
|
||||
writeInfo(url, info, true);;
|
||||
}
|
||||
|
||||
QString Core::UrlStorage::addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id)
|
||||
{
|
||||
QString path;
|
||||
if (!opened) {
|
||||
throw Archive::Closed("addMessageAndCheckForPath", name.toStdString());
|
||||
}
|
||||
|
||||
return addToInfo(url, account, jid, id).getPath();
|
||||
}
|
||||
|
||||
Core::UrlStorage::UrlInfo Core::UrlStorage::addToInfo(const QString& url, const QString& account, const QString& jid, const QString& id, const QString& path)
|
||||
{
|
||||
UrlInfo info;
|
||||
MDB_txn *txn;
|
||||
mdb_txn_begin(environment, NULL, 0, &txn);
|
||||
UrlInfo info;
|
||||
|
||||
try {
|
||||
readInfo(url, info, txn);
|
||||
path = info.getPath();
|
||||
info.addMessage(account, jid, id);
|
||||
try {
|
||||
writeInfo(url, info, txn, true);
|
||||
mdb_txn_commit(txn);
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
} catch (const Archive::NotFound& e) {
|
||||
info.addMessage(account, jid, id);
|
||||
try {
|
||||
writeInfo(url, info, txn, true);
|
||||
mdb_txn_commit(txn);
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
|
||||
return path;
|
||||
bool pathChange = false;
|
||||
bool listChange = false;
|
||||
if (path != "-s") {
|
||||
if (info.getPath() != path) {
|
||||
info.setPath(path);
|
||||
pathChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (account.size() > 0 && jid.size() > 0 && id.size() > 0) {
|
||||
listChange = info.addMessage(account, jid, id);
|
||||
}
|
||||
|
||||
if (pathChange || listChange) {
|
||||
try {
|
||||
writeInfo(url, info, txn, true);
|
||||
mdb_txn_commit(txn);
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
} else {
|
||||
mdb_txn_abort(txn);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::setPath(const QString& url, const QString& path)
|
||||
std::list<Shared::MessageInfo> Core::UrlStorage::setPath(const QString& url, const QString& path)
|
||||
{
|
||||
std::list<MessageInfo> list;
|
||||
std::list<Shared::MessageInfo> list;
|
||||
|
||||
MDB_txn *txn;
|
||||
mdb_txn_begin(environment, NULL, 0, &txn);
|
||||
|
@ -247,24 +267,17 @@ std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::setPath(const QString
|
|||
|
||||
try {
|
||||
readInfo(url, info, txn);
|
||||
info.setPath(path);
|
||||
info.getMessages(list);
|
||||
try {
|
||||
writeInfo(url, info, txn, true);
|
||||
mdb_txn_commit(txn);
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
} catch (const Archive::NotFound& e) {
|
||||
info.setPath(path);
|
||||
try {
|
||||
writeInfo(url, info, txn, true);
|
||||
mdb_txn_commit(txn);
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
}
|
||||
|
||||
info.setPath(path);
|
||||
try {
|
||||
writeInfo(url, info, txn, true);
|
||||
mdb_txn_commit(txn);
|
||||
} catch (...) {
|
||||
mdb_txn_abort(txn);
|
||||
throw;
|
||||
|
@ -273,9 +286,9 @@ std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::setPath(const QString
|
|||
return list;
|
||||
}
|
||||
|
||||
std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::removeFile(const QString& url)
|
||||
std::list<Shared::MessageInfo> Core::UrlStorage::removeFile(const QString& url)
|
||||
{
|
||||
std::list<MessageInfo> list;
|
||||
std::list<Shared::MessageInfo> list;
|
||||
|
||||
MDB_txn *txn;
|
||||
mdb_txn_begin(environment, NULL, 0, &txn);
|
||||
|
@ -313,9 +326,9 @@ std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::removeFile(const QStr
|
|||
return list;
|
||||
}
|
||||
|
||||
std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::deletedFile(const QString& path)
|
||||
std::list<Shared::MessageInfo> Core::UrlStorage::deletedFile(const QString& path)
|
||||
{
|
||||
std::list<MessageInfo> list;
|
||||
std::list<Shared::MessageInfo> list;
|
||||
|
||||
MDB_txn *txn;
|
||||
mdb_txn_begin(environment, NULL, 0, &txn);
|
||||
|
@ -362,6 +375,46 @@ std::list<Core::UrlStorage::MessageInfo> Core::UrlStorage::deletedFile(const QSt
|
|||
}
|
||||
|
||||
|
||||
QString Core::UrlStorage::getUrl(const QString& path)
|
||||
{
|
||||
std::list<Shared::MessageInfo> list;
|
||||
|
||||
MDB_txn *txn;
|
||||
mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
|
||||
|
||||
std::string spath = path.toStdString();
|
||||
|
||||
MDB_val lmdbKey, lmdbData;
|
||||
lmdbKey.mv_size = spath.size();
|
||||
lmdbKey.mv_data = (char*)spath.c_str();
|
||||
|
||||
QString url;
|
||||
int rc = mdb_get(txn, map, &lmdbKey, &lmdbData);
|
||||
|
||||
if (rc == 0) {
|
||||
std::string surl((char*)lmdbData.mv_data, lmdbData.mv_size);
|
||||
url = QString(surl.c_str());
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
return url;
|
||||
} else if (rc == MDB_NOTFOUND) {
|
||||
mdb_txn_abort(txn);
|
||||
throw Archive::NotFound(spath, name.toStdString());
|
||||
} else {
|
||||
mdb_txn_abort(txn);
|
||||
throw Archive::Unknown(name.toStdString(), mdb_strerror(rc));
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<QString, std::list<Shared::MessageInfo>> Core::UrlStorage::getPath(const QString& url)
|
||||
{
|
||||
UrlInfo info;
|
||||
readInfo(url, info);
|
||||
std::list<Shared::MessageInfo> container;
|
||||
info.getMessages(container);
|
||||
return std::make_pair(info.getPath(), container);
|
||||
}
|
||||
|
||||
Core::UrlStorage::UrlInfo::UrlInfo():
|
||||
localPath(),
|
||||
messages() {}
|
||||
|
@ -370,19 +423,29 @@ Core::UrlStorage::UrlInfo::UrlInfo(const QString& path):
|
|||
localPath(path),
|
||||
messages() {}
|
||||
|
||||
Core::UrlStorage::UrlInfo::UrlInfo(const QString& path, const std::list<Shared::MessageInfo>& msgs):
|
||||
localPath(path),
|
||||
messages(msgs) {}
|
||||
|
||||
Core::UrlStorage::UrlInfo::~UrlInfo() {}
|
||||
|
||||
void Core::UrlStorage::UrlInfo::addMessage(const QString& acc, const QString& jid, const QString& id)
|
||||
bool Core::UrlStorage::UrlInfo::addMessage(const QString& acc, const QString& jid, const QString& id)
|
||||
{
|
||||
for (const Shared::MessageInfo& info : messages) {
|
||||
if (info.account == acc && info.jid == jid && info.messageId == id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
messages.emplace_back(acc, jid, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Core::UrlStorage::UrlInfo::serialize(QDataStream& data) const
|
||||
{
|
||||
data << localPath;
|
||||
std::list<MessageInfo>::size_type size = messages.size();
|
||||
std::list<Shared::MessageInfo>::size_type size = messages.size();
|
||||
data << quint32(size);
|
||||
for (const MessageInfo& info : messages) {
|
||||
for (const Shared::MessageInfo& info : messages) {
|
||||
data << info.account;
|
||||
data << info.jid;
|
||||
data << info.messageId;
|
||||
|
@ -396,16 +459,18 @@ void Core::UrlStorage::UrlInfo::deserialize(QDataStream& data)
|
|||
data >> size;
|
||||
for (quint32 i = 0; i < size; ++i) {
|
||||
messages.emplace_back();
|
||||
MessageInfo& info = messages.back();
|
||||
Shared::MessageInfo& info = messages.back();
|
||||
data >> info.account;
|
||||
data >> info.jid;
|
||||
data >> info.messageId;
|
||||
}
|
||||
}
|
||||
|
||||
void Core::UrlStorage::UrlInfo::getMessages(std::list<MessageInfo>& container) const
|
||||
void Core::UrlStorage::UrlInfo::getMessages(std::list<Shared::MessageInfo>& container) const
|
||||
{
|
||||
std::copy(messages.begin(), messages.end(), container.end());
|
||||
for (const Shared::MessageInfo& info : messages) {
|
||||
container.emplace_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
QString Core::UrlStorage::UrlInfo::getPath() const
|
||||
|
@ -423,13 +488,3 @@ void Core::UrlStorage::UrlInfo::setPath(const QString& path)
|
|||
{
|
||||
localPath = path;
|
||||
}
|
||||
|
||||
Core::UrlStorage::MessageInfo::MessageInfo():
|
||||
account(),
|
||||
jid(),
|
||||
messageId() {}
|
||||
|
||||
Core::UrlStorage::MessageInfo::MessageInfo(const QString& acc, const QString& j, const QString& id):
|
||||
account(acc),
|
||||
jid(j),
|
||||
messageId(id) {}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <list>
|
||||
|
||||
#include "archive.h"
|
||||
#include <shared/messageinfo.h>
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
@ -35,15 +36,6 @@ class UrlStorage
|
|||
{
|
||||
class UrlInfo;
|
||||
public:
|
||||
struct MessageInfo {
|
||||
MessageInfo();
|
||||
MessageInfo(const QString& acc, const QString& j, const QString& id);
|
||||
|
||||
QString account;
|
||||
QString jid;
|
||||
QString messageId;
|
||||
};
|
||||
|
||||
UrlStorage(const QString& name);
|
||||
~UrlStorage();
|
||||
|
||||
|
@ -54,10 +46,13 @@ public:
|
|||
void addFile(const QString& url, const QString& path);
|
||||
void addFile(const QString& url, const QString& account, const QString& jid, const QString& id);
|
||||
void addFile(const QString& url, const QString& path, const QString& account, const QString& jid, const QString& id);
|
||||
std::list<MessageInfo> removeFile(const QString& url); //removes entry like it never was in the database, returns affected message infos
|
||||
std::list<MessageInfo> deletedFile(const QString& path); //empties the localPath of the entry, returns affected message infos
|
||||
std::list<MessageInfo> setPath(const QString& url, const QString& path);
|
||||
void addFile(const std::list<Shared::MessageInfo>& msgs, const QString& url, const QString& path); //this one overwrites all that was
|
||||
std::list<Shared::MessageInfo> removeFile(const QString& url); //removes entry like it never was in the database, returns affected message infos
|
||||
std::list<Shared::MessageInfo> deletedFile(const QString& path); //empties the localPath of the entry, returns affected message infos
|
||||
std::list<Shared::MessageInfo> setPath(const QString& url, const QString& path);
|
||||
QString getUrl(const QString& path);
|
||||
QString addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id);
|
||||
std::pair<QString, std::list<Shared::MessageInfo>> getPath(const QString& url);
|
||||
|
||||
private:
|
||||
QString name;
|
||||
|
@ -71,11 +66,13 @@ private:
|
|||
void writeInfo(const QString& key, const UrlInfo& info, MDB_txn* txn, bool overwrite = false);
|
||||
void readInfo(const QString& key, UrlInfo& info);
|
||||
void readInfo(const QString& key, UrlInfo& info, MDB_txn* txn);
|
||||
UrlInfo addToInfo(const QString& url, const QString& account, const QString& jid, const QString& id, const QString& path = "-s");
|
||||
|
||||
private:
|
||||
class UrlInfo {
|
||||
public:
|
||||
UrlInfo(const QString& path);
|
||||
UrlInfo(const QString& path, const std::list<Shared::MessageInfo>& msgs);
|
||||
UrlInfo();
|
||||
~UrlInfo();
|
||||
|
||||
|
@ -86,12 +83,12 @@ private:
|
|||
bool hasPath() const;
|
||||
void setPath(const QString& path);
|
||||
|
||||
void addMessage(const QString& acc, const QString& jid, const QString& id);
|
||||
void getMessages(std::list<MessageInfo>& container) const;
|
||||
bool addMessage(const QString& acc, const QString& jid, const QString& id);
|
||||
void getMessages(std::list<Shared::MessageInfo>& container) const;
|
||||
|
||||
private:
|
||||
QString localPath;
|
||||
std::list<MessageInfo> messages;
|
||||
std::list<Shared::MessageInfo> messages;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue