From 5fbb03fc4604279c6836c7baa8ca837b8a306db0 Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 15 Apr 2023 15:07:27 -0300 Subject: [PATCH] transitioned urlstorage to LMDBAL, made it possible to build against latest qxmpp --- CMakeLists.txt | 10 +- core/components/CMakeLists.txt | 2 + core/components/networkaccess.cpp | 126 +++--- core/components/networkaccess.h | 6 +- core/components/urlstorage.cpp | 289 +++++++++++++ core/{storage => components}/urlstorage.h | 28 +- core/storage/CMakeLists.txt | 6 - core/storage/urlstorage.cpp | 491 ---------------------- external/qxmpp | 2 +- main/main.cpp | 2 +- 10 files changed, 363 insertions(+), 599 deletions(-) create mode 100644 core/components/urlstorage.cpp rename core/{storage => components}/urlstorage.h (90%) delete mode 100644 core/storage/urlstorage.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cdb712..06c4344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,16 +143,18 @@ if (NOT SYSTEM_QXMPP) endif () add_subdirectory(external/qxmpp) - target_link_libraries(squawk PRIVATE qxmpp) - target_link_libraries(squawk PRIVATE QXmppOmemo) + target_link_libraries(squawk PRIVATE QXmppQt${QT_VERSION_MAJOR}) + if (WITH_OMEMO) + target_link_libraries(squawk PRIVATE QXmppOmemoQt${QT_VERSION_MAJOR}) + endif () else () target_link_libraries(squawk PRIVATE QXmpp::QXmpp) endif () ## LMDBAL if (SYSTEM_LMDBAL) - find_package(lmdbal CONFIG) - if (NOT LMDBAL_FOUND) + find_package(lmdbal) + if (NOT lmdbal_FOUND) set(SYSTEM_LMDBAL OFF) message("LMDBAL package wasn't found, trying to build with bundled LMDBAL") else () diff --git a/core/components/CMakeLists.txt b/core/components/CMakeLists.txt index b78794a..86d9fb8 100644 --- a/core/components/CMakeLists.txt +++ b/core/components/CMakeLists.txt @@ -1,11 +1,13 @@ set(SOURCE_FILES networkaccess.cpp clientcache.cpp + urlstorage.cpp ) set(HEADER_FILES networkaccess.h clientcache.h + urlstorage.h ) target_sources(squawk PRIVATE diff --git a/core/components/networkaccess.cpp b/core/components/networkaccess.cpp index 22bb7a2..862c664 100644 --- a/core/components/networkaccess.cpp +++ b/core/components/networkaccess.cpp @@ -35,13 +35,11 @@ Core::NetworkAccess::NetworkAccess(QObject* parent): currentPath = settings.value("downloadsPath").toString(); } -Core::NetworkAccess::~NetworkAccess() -{ +Core::NetworkAccess::~NetworkAccess() { stop(); } -void Core::NetworkAccess::downladFile(const QString& url) -{ +void Core::NetworkAccess::downladFile(const QString& url) { std::map::iterator itr = downloads.find(url); if (itr != downloads.end()) { qDebug() << "NetworkAccess received a request to download a file" << url << ", but the file is currently downloading, skipping"; @@ -50,27 +48,25 @@ void Core::NetworkAccess::downladFile(const QString& url) std::pair> p = storage.getPath(url); if (p.first.size() > 0) { QFileInfo info(p.first); - if (info.exists() && info.isFile()) { + if (info.exists() && info.isFile()) emit downloadFileComplete(p.second, p.first); - } else { + else startDownload(p.second, url); - } } else { startDownload(p.second, url); } - } catch (const Archive::NotFound& e) { + } catch (const LMDBAL::NotFound& e) { 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(), url); - } catch (const Archive::Unknown& e) { + } catch (const LMDBAL::Unknown& e) { qDebug() << "Error requesting file path:" << e.what(); emit loadFileError(std::list(), QString("Database error: ") + e.what(), false); } } } -void Core::NetworkAccess::start() -{ +void Core::NetworkAccess::start() { if (!running) { manager = new QNetworkAccessManager(); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) @@ -81,8 +77,7 @@ void Core::NetworkAccess::start() } } -void Core::NetworkAccess::stop() -{ +void Core::NetworkAccess::stop() { if (running) { storage.close(); manager->deleteLater(); @@ -96,8 +91,7 @@ void Core::NetworkAccess::stop() } } -void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ +void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { QNetworkReply* rpl = static_cast(sender()); QString url = rpl->url().toString(); std::map::const_iterator itr = downloads.find(url); @@ -115,8 +109,7 @@ void Core::NetworkAccess::onDownloadProgress(qint64 bytesReceived, qint64 bytesT } } -void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code) -{ +void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code) { qDebug() << "DEBUG: DOWNLOAD ERROR"; QNetworkReply* rpl = static_cast(sender()); qDebug() << rpl->errorString(); @@ -134,8 +127,7 @@ void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code) } } -void Core::NetworkAccess::onDownloadSSLError(const QList& errors) -{ +void Core::NetworkAccess::onDownloadSSLError(const QList& errors) { qDebug() << "DEBUG: DOWNLOAD SSL ERRORS"; for (const QSslError& err : errors) { qDebug() << err.errorString(); @@ -154,9 +146,7 @@ void Core::NetworkAccess::onDownloadSSLError(const QList& errors) } } - -QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code) -{ +QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code) { QString errorText(""); switch (code) { case QNetworkReply::NoError: @@ -280,8 +270,7 @@ QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code) } -void Core::NetworkAccess::onDownloadFinished() -{ +void Core::NetworkAccess::onDownloadFinished() { qDebug() << "DEBUG: DOWNLOAD FINISHED"; QNetworkReply* rpl = static_cast(sender()); QString url = rpl->url().toString(); @@ -296,11 +285,11 @@ void Core::NetworkAccess::onDownloadFinished() QStringList hops = url.split("/"); QString fileName = hops.back(); QString jid; - if (dwn->messages.size() > 0) { + if (dwn->messages.size() > 0) jid = dwn->messages.front().jid; - } else { + else qDebug() << "An attempt to save the file but it doesn't seem to belong to any message, download is definately going to be broken"; - } + QString path = prepareDirectory(jid); if (path.size() > 0) { path = checkFileName(fileName, path); @@ -319,11 +308,10 @@ void Core::NetworkAccess::onDownloadFinished() err = "Couldn't prepare a directory for file"; } - if (path.size() > 0) { + if (path.size() > 0) emit downloadFileComplete(dwn->messages, path); - } else { + else emit loadFileError(dwn->messages, "Error saving file " + url + "; " + err, false); - } } dwn->reply->deleteLater(); @@ -332,8 +320,7 @@ void Core::NetworkAccess::onDownloadFinished() } } -void Core::NetworkAccess::startDownload(const std::list& msgs, const QString& url) -{ +void Core::NetworkAccess::startDownload(const std::list& msgs, const QString& url) { Transfer* dwn = new Transfer({msgs, 0, 0, true, "", url, 0}); QNetworkRequest req(url); dwn->reply = manager->get(req); @@ -349,8 +336,7 @@ void Core::NetworkAccess::startDownload(const std::list& ms emit loadFileProgress(dwn->messages, 0, false); } -void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code) -{ +void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code) { QNetworkReply* rpl = static_cast(sender()); QString url = rpl->url().toString(); std::map::const_iterator itr = uploads.find(url); @@ -368,8 +354,7 @@ void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code) } } -void Core::NetworkAccess::onUploadFinished() -{ +void Core::NetworkAccess::onUploadFinished() { QNetworkReply* rpl = static_cast(sender()); QString url = rpl->url().toString(); std::map::const_iterator itr = uploads.find(url); @@ -389,20 +374,16 @@ void Core::NetworkAccess::onUploadFinished() // Copy {TEMPDIR}/squawk_img_attach_XXXXXX.png to Download folder bool copyResult = QFile::copy(upl->path, Shared::resolvePath(newPath)); - - if (copyResult) { - // Change storage - upl->path = newPath; - } else { + if (copyResult) + upl->path = newPath; // Change storage + else err = "copying to " + newPath + " failed"; - } } else { err = "Couldn't prepare a directory for file"; } - if (err.size() != 0) { + if (err.size() != 0) qDebug() << "failed to copy temporary upload file " << upl->path << " to download folder:" << err; - } } storage.addFile(upl->messages, upl->url, upl->path); @@ -417,8 +398,7 @@ void Core::NetworkAccess::onUploadFinished() } } -void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ +void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTotal) { QNetworkReply* rpl = static_cast(sender()); QString url = rpl->url().toString(); std::map::const_iterator itr = uploads.find(url); @@ -436,13 +416,12 @@ void Core::NetworkAccess::onUploadProgress(qint64 bytesReceived, qint64 bytesTot } } -QString Core::NetworkAccess::getFileRemoteUrl(const QString& path) -{ +QString Core::NetworkAccess::getFileRemoteUrl(const QString& path) { QString p = Shared::squawkifyPath(path); try { p = storage.getUrl(p); - } catch (const Archive::NotFound& err) { + } catch (const LMDBAL::NotFound& err) { p = ""; } catch (...) { throw; @@ -451,8 +430,13 @@ QString Core::NetworkAccess::getFileRemoteUrl(const QString& path) return p; } -void Core::NetworkAccess::uploadFile(const Shared::MessageInfo& info, const QString& path, const QUrl& put, const QUrl& get, const QMap headers) -{ +void Core::NetworkAccess::uploadFile( + const Shared::MessageInfo& info, + const QString& path, + const QUrl& put, + const QUrl& get, + const QMap headers +) { QFile* file = new QFile(path); Transfer* upl = new Transfer({{info}, 0, 0, true, path, get.toString(), file}); QNetworkRequest req(put); @@ -479,22 +463,18 @@ void Core::NetworkAccess::uploadFile(const Shared::MessageInfo& info, const QStr } } -void Core::NetworkAccess::registerFile(const QString& url, const QString& account, const QString& jid, const QString& id) -{ +void Core::NetworkAccess::registerFile(const QString& url, const QString& account, const QString& jid, const QString& id) { storage.addFile(url, account, jid, id); std::map::iterator itr = downloads.find(url); - if (itr != downloads.end()) { + 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) -{ +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) -{ +bool Core::NetworkAccess::checkAndAddToUploading(const QString& acc, const QString& jid, const QString id, const QString path) { for (const std::pair& pair : uploads) { Transfer* info = pair.second; if (pair.second->path == path) { @@ -516,8 +496,7 @@ bool Core::NetworkAccess::checkAndAddToUploading(const QString& acc, const QStri return false; } -QString Core::NetworkAccess::prepareDirectory(const QString& jid) -{ +QString Core::NetworkAccess::prepareDirectory(const QString& jid) { QString path = currentPath; QString addition; if (jid.size() > 0) { @@ -529,25 +508,23 @@ QString Core::NetworkAccess::prepareDirectory(const QString& jid) if (!location.exists()) { bool res = location.mkpath(path); - if (!res) { + if (!res) return ""; - } else { + else return "squawk://" + addition; - } } return "squawk://" + addition; } -QString Core::NetworkAccess::checkFileName(const QString& name, const QString& 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) { + for (QStringList::const_iterator sEnd = parts.end(); sItr != sEnd; ++sItr) suffix += "." + (*sItr); - } + QString postfix(""); QString resolvedPath = Shared::resolvePath(path); QString count(""); @@ -562,18 +539,15 @@ QString Core::NetworkAccess::checkFileName(const QString& name, const QString& p return path + QDir::separator() + realName + count + suffix; } -QString Core::NetworkAccess::addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id) -{ +QString Core::NetworkAccess::addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id) { return storage.addMessageAndCheckForPath(url, account, jid, id); } -std::list Core::NetworkAccess::reportPathInvalid(const QString& path) -{ +std::list Core::NetworkAccess::reportPathInvalid(const QString& path) { return storage.deletedFile(path); } -void Core::NetworkAccess::moveFilesDirectory(const QString& newPath) -{ +void Core::NetworkAccess::moveFilesDirectory(const QString& newPath) { QDir dir(currentPath); bool success = true; qDebug() << "moving" << currentPath << "to" << newPath; @@ -582,8 +556,8 @@ void Core::NetworkAccess::moveFilesDirectory(const QString& newPath) success = dir.rename(fileName, newPath + QDir::separator() + fileName) && success; } - if (!success) { + if (!success) qDebug() << "couldn't move downloads directory, most probably downloads will be broken"; - } + currentPath = newPath; } diff --git a/core/components/networkaccess.h b/core/components/networkaccess.h index c94c22a..99a15ed 100644 --- a/core/components/networkaccess.h +++ b/core/components/networkaccess.h @@ -30,15 +30,11 @@ #include -#include #include +#include "urlstorage.h" 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 { diff --git a/core/components/urlstorage.cpp b/core/components/urlstorage.cpp new file mode 100644 index 0000000..c745236 --- /dev/null +++ b/core/components/urlstorage.cpp @@ -0,0 +1,289 @@ +/* + * Squawk messenger. + * Copyright (C) 2019 Yury Gubich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "urlstorage.h" + +Core::UrlStorage::UrlStorage(const QString& p_name): + base(p_name), + urlToInfo(base.addStorage("urlToInfo")), + pathToUrl(base.addStorage("pathToUrl")) +{} + +Core::UrlStorage::~UrlStorage() { + close(); +} + +void Core::UrlStorage::open() { + base.open(); +} + +void Core::UrlStorage::close() { + base.close(); +} + +void Core::UrlStorage::writeInfo(const QString& key, const Core::UrlStorage::UrlInfo& info, bool overwrite) { + LMDBAL::TransactionID txn = base.beginTransaction(); + + try { + writeInfo(key, info, txn, overwrite); + base.commitTransaction(txn); + } catch (...) { + base.abortTransaction(txn); + throw; + } +} + +void Core::UrlStorage::writeInfo(const QString& key, const Core::UrlStorage::UrlInfo& info, MDB_txn* txn, bool overwrite) { + if (overwrite) + urlToInfo->forceRecord(key, info, txn); + else + urlToInfo->addRecord(key, info, txn); + + if (info.hasPath()) + pathToUrl->forceRecord(info.getPath(), key, txn); +} + +void Core::UrlStorage::addFile(const QString& url) { + addToInfo(url, "", "", ""); +} + +void Core::UrlStorage::addFile(const QString& url, const QString& path) { + addToInfo(url, "", "", "", path); +} + +void Core::UrlStorage::addFile(const QString& url, const QString& account, const QString& jid, const QString& id) { + addToInfo(url, account, jid, id); +} + +void Core::UrlStorage::addFile(const QString& url, const QString& path, const QString& account, const QString& jid, const QString& id) { + addToInfo(url, account, jid, id, path); +} + +void Core::UrlStorage::addFile(const std::list& msgs, const QString& url, const QString& path) { + UrlInfo info (path, msgs); + writeInfo(url, info, true); +} + +QString Core::UrlStorage::addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id){ + 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; + LMDBAL::TransactionID txn = base.beginTransaction(); + + try { + urlToInfo->getRecord(url, info, txn); + } catch (const LMDBAL::NotFound& e) { + } catch (...) { + base.abortTransaction(txn); + throw; + } + + 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); + base.commitTransaction(txn); + } catch (...) { + base.abortTransaction(txn); + throw; + } + } else { + base.abortTransaction(txn); + } + + return info; +} + +std::list Core::UrlStorage::setPath(const QString& url, const QString& path) { + std::list list; + LMDBAL::TransactionID txn = base.beginTransaction(); + UrlInfo info; + + try { + urlToInfo->getRecord(url, info, txn); + info.getMessages(list); + } catch (const LMDBAL::NotFound& e) { + } catch (...) { + base.abortTransaction(txn); + throw; + } + + info.setPath(path); + try { + writeInfo(url, info, txn, true); + base.commitTransaction(txn); + } catch (...) { + base.abortTransaction(txn); + throw; + } + + return list; +} + +std::list Core::UrlStorage::removeFile(const QString& url) { + std::list list; + LMDBAL::TransactionID txn = base.beginTransaction(); + UrlInfo info; + + try { + urlToInfo->getRecord(url, info, txn); + urlToInfo->removeRecord(url); + info.getMessages(list); + + if (info.hasPath()) + pathToUrl->removeRecord(info.getPath()); + + base.commitTransaction(txn); + } catch (...) { + base.abortTransaction(txn); + throw; + } + + return list; +} + +std::list Core::UrlStorage::deletedFile(const QString& path) { + std::list list; + LMDBAL::TransactionID txn = base.beginTransaction(); + + try { + QString url = pathToUrl->getRecord(path, txn); + pathToUrl->removeRecord(path); + + UrlInfo info = urlToInfo->getRecord(url, txn); + info.getMessages(list); + info.setPath(QString()); + urlToInfo->changeRecord(url, info, txn); + + base.commitTransaction(txn); + } catch (...) { + base.abortTransaction(txn); + throw; + } + + return list; +} + +QString Core::UrlStorage::getUrl(const QString& path) { + return pathToUrl->getRecord(path); +} + +std::pair> Core::UrlStorage::getPath(const QString& url) { + UrlInfo info = urlToInfo->getRecord(url); + std::list container; + info.getMessages(container); + return std::make_pair(info.getPath(), container); +} + +Core::UrlStorage::UrlInfo::UrlInfo(): + localPath(), + messages() {} + +Core::UrlStorage::UrlInfo::UrlInfo(const QString& path): + localPath(path), + messages() {} + +Core::UrlStorage::UrlInfo::UrlInfo(const QString& path, const std::list& msgs): + localPath(path), + messages(msgs) {} + +Core::UrlStorage::UrlInfo::~UrlInfo() {} + +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::size_type size = messages.size(); + data << quint32(size); + for (const Shared::MessageInfo& info : messages) { + data << info.account; + data << info.jid; + data << info.messageId; + } +} + +QDataStream & operator << (QDataStream& in, const Core::UrlStorage::UrlInfo& info) { + info.serialize(in); + return in; +} + +QDataStream & operator >> (QDataStream& out, Core::UrlStorage::UrlInfo& info) { + info.deserialize(out); + return out; +} + +void Core::UrlStorage::UrlInfo::deserialize(QDataStream& data) { + data >> localPath; + quint32 size; + data >> size; + for (quint32 i = 0; i < size; ++i) { + messages.emplace_back(); + Shared::MessageInfo& info = messages.back(); + data >> info.account; + data >> info.jid; + data >> info.messageId; + } +} + +void Core::UrlStorage::UrlInfo::getMessages(std::list& container) const { + for (const Shared::MessageInfo& info : messages) + container.emplace_back(info); +} + +QString Core::UrlStorage::UrlInfo::getPath() const { + return localPath; +} + +bool Core::UrlStorage::UrlInfo::hasPath() const { + return localPath.size() > 0; +} + +void Core::UrlStorage::UrlInfo::setPath(const QString& path) { + localPath = path; +} diff --git a/core/storage/urlstorage.h b/core/components/urlstorage.h similarity index 90% rename from core/storage/urlstorage.h rename to core/components/urlstorage.h index 3dc5c21..ee8e30d 100644 --- a/core/storage/urlstorage.h +++ b/core/components/urlstorage.h @@ -21,20 +21,19 @@ #include #include -#include + #include -#include "archive.h" +#include + #include namespace Core { -/** - * @todo write docs - */ -class UrlStorage -{ +class UrlStorage { +public: class UrlInfo; + public: UrlStorage(const QString& name); ~UrlStorage(); @@ -55,20 +54,16 @@ public: std::pair> getPath(const QString& url); private: - QString name; - bool opened; - MDB_env* environment; - MDB_dbi base; - MDB_dbi map; + LMDBAL::Base base; + LMDBAL::Storage* urlToInfo; + LMDBAL::Storage* pathToUrl; private: void writeInfo(const QString& key, const UrlInfo& info, bool overwrite = false); 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: +public: class UrlInfo { public: UrlInfo(const QString& path); @@ -96,4 +91,7 @@ private: } +QDataStream& operator >> (QDataStream &in, Core::UrlStorage::UrlInfo& info); +QDataStream& operator << (QDataStream &out, const Core::UrlStorage::UrlInfo& info); + #endif // CORE_URLSTORAGE_H diff --git a/core/storage/CMakeLists.txt b/core/storage/CMakeLists.txt index 238b59a..e2de42c 100644 --- a/core/storage/CMakeLists.txt +++ b/core/storage/CMakeLists.txt @@ -1,10 +1,4 @@ target_sources(squawk PRIVATE archive.cpp archive.h -# storage.hpp -# storage.h - urlstorage.cpp - urlstorage.h -# cache.hpp -# cache.h ) diff --git a/core/storage/urlstorage.cpp b/core/storage/urlstorage.cpp deleted file mode 100644 index f59ff62..0000000 --- a/core/storage/urlstorage.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Squawk messenger. - * Copyright (C) 2019 Yury Gubich - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -#include "urlstorage.h" - -Core::UrlStorage::UrlStorage(const QString& p_name): - name(p_name), - opened(false), - environment(), - base(), - map() -{ -} - -Core::UrlStorage::~UrlStorage() -{ - close(); -} - -void Core::UrlStorage::open() -{ - if (!opened) { - mdb_env_create(&environment); - QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); - path += "/" + name; - QDir cache(path); - - if (!cache.exists()) { - bool res = cache.mkpath(path); - if (!res) { - throw Archive::Directory(path.toStdString()); - } - } - - mdb_env_set_maxdbs(environment, 2); - mdb_env_set_mapsize(environment, 10UL * 1024UL * 1024UL); - mdb_env_open(environment, path.toStdString().c_str(), 0, 0664); - - MDB_txn *txn; - mdb_txn_begin(environment, NULL, 0, &txn); - mdb_dbi_open(txn, "base", MDB_CREATE, &base); - mdb_dbi_open(txn, "map", MDB_CREATE, &map); - mdb_txn_commit(txn); - opened = true; - } -} - -void Core::UrlStorage::close() -{ - if (opened) { - mdb_dbi_close(environment, map); - mdb_dbi_close(environment, base); - mdb_env_close(environment); - opened = false; - } -} - -void Core::UrlStorage::writeInfo(const QString& key, const Core::UrlStorage::UrlInfo& info, bool overwrite) -{ - MDB_txn *txn; - mdb_txn_begin(environment, NULL, 0, &txn); - - try { - writeInfo(key, info, txn, overwrite); - mdb_txn_commit(txn); - } catch (...) { - mdb_txn_abort(txn); - throw; - } -} - -void Core::UrlStorage::writeInfo(const QString& key, const Core::UrlStorage::UrlInfo& info, MDB_txn* txn, bool overwrite) -{ - QByteArray ba; - QDataStream ds(&ba, QIODevice::WriteOnly); - info.serialize(ds); - - const std::string& id = key.toStdString(); - MDB_val lmdbKey, lmdbData; - lmdbKey.mv_size = id.size(); - lmdbKey.mv_data = (char*)id.c_str(); - lmdbData.mv_size = ba.size(); - lmdbData.mv_data = (uint8_t*)ba.data(); - - int rc; - rc = mdb_put(txn, base, &lmdbKey, &lmdbData, overwrite ? 0 : MDB_NOOVERWRITE); - - if (rc != 0) { - if (rc == MDB_KEYEXIST) { - if (!overwrite) { - throw Archive::Exist(name.toStdString(), id); - } - } else { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } - } - - if (info.hasPath()) { - std::string sp = info.getPath().toStdString(); - lmdbData.mv_size = sp.size(); - lmdbData.mv_data = (char*)sp.c_str(); - rc = mdb_put(txn, map, &lmdbData, &lmdbKey, 0); - if (rc != 0) { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } - } -} - -void Core::UrlStorage::readInfo(const QString& key, Core::UrlStorage::UrlInfo& info, MDB_txn* txn) -{ - const std::string& id = key.toStdString(); - MDB_val lmdbKey, lmdbData; - lmdbKey.mv_size = id.size(); - lmdbKey.mv_data = (char*)id.c_str(); - int rc = mdb_get(txn, base, &lmdbKey, &lmdbData); - - if (rc == 0) { - QByteArray ba((char*)lmdbData.mv_data, lmdbData.mv_size); - QDataStream ds(&ba, QIODevice::ReadOnly); - - info.deserialize(ds); - } else if (rc == MDB_NOTFOUND) { - throw Archive::NotFound(id, name.toStdString()); - } else { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } -} - -void Core::UrlStorage::readInfo(const QString& key, Core::UrlStorage::UrlInfo& info) -{ - MDB_txn *txn; - mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn); - - try { - readInfo(key, info, txn); - mdb_txn_commit(txn); - } catch (...) { - mdb_txn_abort(txn); - throw; - } -} - -void Core::UrlStorage::addFile(const QString& url) -{ - if (!opened) { - throw Archive::Closed("addFile(no message, no path)", name.toStdString()); - } - - addToInfo(url, "", "", ""); -} - -void Core::UrlStorage::addFile(const QString& url, const QString& path) -{ - if (!opened) { - throw Archive::Closed("addFile(no message, with path)", name.toStdString()); - } - - addToInfo(url, "", "", "", path); -} - -void Core::UrlStorage::addFile(const QString& url, const QString& account, const QString& jid, const QString& id) -{ - if (!opened) { - throw Archive::Closed("addFile(with message, no path)", name.toStdString()); - } - - addToInfo(url, account, jid, id); -} - -void Core::UrlStorage::addFile(const QString& url, const QString& path, const QString& account, const QString& jid, const QString& id) -{ - if (!opened) { - throw Archive::Closed("addFile(with message, with path)", name.toStdString()); - } - - addToInfo(url, account, jid, id, path); -} - -void Core::UrlStorage::addFile(const std::list& 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) -{ - 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); - - try { - readInfo(url, info, txn); - } catch (const Archive::NotFound& e) { - - } catch (...) { - mdb_txn_abort(txn); - throw; - } - - 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::setPath(const QString& url, const QString& path) -{ - std::list list; - - MDB_txn *txn; - mdb_txn_begin(environment, NULL, 0, &txn); - UrlInfo info; - - try { - readInfo(url, info, txn); - info.getMessages(list); - } catch (const Archive::NotFound& e) { - } 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; - } - - return list; -} - -std::list Core::UrlStorage::removeFile(const QString& url) -{ - std::list list; - - MDB_txn *txn; - mdb_txn_begin(environment, NULL, 0, &txn); - UrlInfo info; - - try { - std::string id = url.toStdString(); - readInfo(url, info, txn); - info.getMessages(list); - - MDB_val lmdbKey; - lmdbKey.mv_size = id.size(); - lmdbKey.mv_data = (char*)id.c_str(); - int rc = mdb_del(txn, base, &lmdbKey, NULL); - if (rc != 0) { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } - - if (info.hasPath()) { - std::string path = info.getPath().toStdString(); - lmdbKey.mv_size = path.size(); - lmdbKey.mv_data = (char*)path.c_str(); - - int rc = mdb_del(txn, map, &lmdbKey, NULL); - if (rc != 0) { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } - } - mdb_txn_commit(txn); - } catch (...) { - mdb_txn_abort(txn); - throw; - } - - return list; -} - -std::list Core::UrlStorage::deletedFile(const QString& path) -{ - std::list list; - - MDB_txn *txn; - mdb_txn_begin(environment, NULL, 0, &txn); - - try { - 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()); - } else if (rc == MDB_NOTFOUND) { - qDebug() << "Have been asked to remove file" << path << ", which isn't in the database, skipping"; - mdb_txn_abort(txn); - return list; - } else { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } - - UrlInfo info; - std::string id = url.toStdString(); - readInfo(url, info, txn); - info.getMessages(list); - info.setPath(QString()); - writeInfo(url, info, txn, true); - - rc = mdb_del(txn, map, &lmdbKey, NULL); - if (rc != 0) { - throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); - } - - mdb_txn_commit(txn); - } catch (...) { - mdb_txn_abort(txn); - throw; - } - - return list; -} - - -QString Core::UrlStorage::getUrl(const QString& path) -{ - std::list 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> Core::UrlStorage::getPath(const QString& url) -{ - UrlInfo info; - readInfo(url, info); - std::list container; - info.getMessages(container); - return std::make_pair(info.getPath(), container); -} - -Core::UrlStorage::UrlInfo::UrlInfo(): - localPath(), - messages() {} - -Core::UrlStorage::UrlInfo::UrlInfo(const QString& path): - localPath(path), - messages() {} - -Core::UrlStorage::UrlInfo::UrlInfo(const QString& path, const std::list& msgs): - localPath(path), - messages(msgs) {} - -Core::UrlStorage::UrlInfo::~UrlInfo() {} - -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::size_type size = messages.size(); - data << quint32(size); - for (const Shared::MessageInfo& info : messages) { - data << info.account; - data << info.jid; - data << info.messageId; - } -} - -void Core::UrlStorage::UrlInfo::deserialize(QDataStream& data) -{ - data >> localPath; - quint32 size; - data >> size; - for (quint32 i = 0; i < size; ++i) { - messages.emplace_back(); - Shared::MessageInfo& info = messages.back(); - data >> info.account; - data >> info.jid; - data >> info.messageId; - } -} - -void Core::UrlStorage::UrlInfo::getMessages(std::list& container) const -{ - for (const Shared::MessageInfo& info : messages) { - container.emplace_back(info); - } -} - -QString Core::UrlStorage::UrlInfo::getPath() const -{ - return localPath; -} - -bool Core::UrlStorage::UrlInfo::hasPath() const -{ - return localPath.size() > 0; -} - - -void Core::UrlStorage::UrlInfo::setPath(const QString& path) -{ - localPath = path; -} diff --git a/external/qxmpp b/external/qxmpp index d679ad1..ab4bdf2 160000 --- a/external/qxmpp +++ b/external/qxmpp @@ -1 +1 @@ -Subproject commit d679ad1c49eeb28be2ac3a75bd7fd1a9be24d483 +Subproject commit ab4bdf2da41a26f462fe3a333a34e32c999e2a6d diff --git a/main/main.cpp b/main/main.cpp index ce614b3..d9ad4cc 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -43,6 +43,7 @@ int main(int argc, char *argv[]) qRegisterMetaType("Shared::EncryptionProtocol"); qRegisterMetaType("Shared::KeyInfo"); qRegisterMetaType("Shared::Info"); + qRegisterMetaType("Shared::TrustLevel"); #ifdef WITH_OMEMO qRegisterMetaType("QXmppOmemoStorage::OwnDevice"); qRegisterMetaTypeStreamOperators("QXmppOmemoStorage::OwnDevice"); @@ -53,7 +54,6 @@ int main(int argc, char *argv[]) if (!app.initializeSettings()) return -1; - return app.run(); }