transitioned urlstorage to LMDBAL, made it possible to build against latest qxmpp
This commit is contained in:
parent
81cf0f8d34
commit
5fbb03fc46
@ -143,16 +143,18 @@ if (NOT SYSTEM_QXMPP)
|
|||||||
endif ()
|
endif ()
|
||||||
add_subdirectory(external/qxmpp)
|
add_subdirectory(external/qxmpp)
|
||||||
|
|
||||||
target_link_libraries(squawk PRIVATE qxmpp)
|
target_link_libraries(squawk PRIVATE QXmppQt${QT_VERSION_MAJOR})
|
||||||
target_link_libraries(squawk PRIVATE QXmppOmemo)
|
if (WITH_OMEMO)
|
||||||
|
target_link_libraries(squawk PRIVATE QXmppOmemoQt${QT_VERSION_MAJOR})
|
||||||
|
endif ()
|
||||||
else ()
|
else ()
|
||||||
target_link_libraries(squawk PRIVATE QXmpp::QXmpp)
|
target_link_libraries(squawk PRIVATE QXmpp::QXmpp)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
## LMDBAL
|
## LMDBAL
|
||||||
if (SYSTEM_LMDBAL)
|
if (SYSTEM_LMDBAL)
|
||||||
find_package(lmdbal CONFIG)
|
find_package(lmdbal)
|
||||||
if (NOT LMDBAL_FOUND)
|
if (NOT lmdbal_FOUND)
|
||||||
set(SYSTEM_LMDBAL OFF)
|
set(SYSTEM_LMDBAL OFF)
|
||||||
message("LMDBAL package wasn't found, trying to build with bundled LMDBAL")
|
message("LMDBAL package wasn't found, trying to build with bundled LMDBAL")
|
||||||
else ()
|
else ()
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
networkaccess.cpp
|
networkaccess.cpp
|
||||||
clientcache.cpp
|
clientcache.cpp
|
||||||
|
urlstorage.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
networkaccess.h
|
networkaccess.h
|
||||||
clientcache.h
|
clientcache.h
|
||||||
|
urlstorage.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(squawk PRIVATE
|
target_sources(squawk PRIVATE
|
||||||
|
@ -35,13 +35,11 @@ Core::NetworkAccess::NetworkAccess(QObject* parent):
|
|||||||
currentPath = settings.value("downloadsPath").toString();
|
currentPath = settings.value("downloadsPath").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::NetworkAccess::~NetworkAccess()
|
Core::NetworkAccess::~NetworkAccess() {
|
||||||
{
|
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::downladFile(const QString& url)
|
void Core::NetworkAccess::downladFile(const QString& url) {
|
||||||
{
|
|
||||||
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
||||||
if (itr != downloads.end()) {
|
if (itr != downloads.end()) {
|
||||||
qDebug() << "NetworkAccess received a request to download a file" << url << ", but the file is currently downloading, skipping";
|
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<QString, std::list<Shared::MessageInfo>> p = storage.getPath(url);
|
std::pair<QString, std::list<Shared::MessageInfo>> p = storage.getPath(url);
|
||||||
if (p.first.size() > 0) {
|
if (p.first.size() > 0) {
|
||||||
QFileInfo info(p.first);
|
QFileInfo info(p.first);
|
||||||
if (info.exists() && info.isFile()) {
|
if (info.exists() && info.isFile())
|
||||||
emit downloadFileComplete(p.second, p.first);
|
emit downloadFileComplete(p.second, p.first);
|
||||||
|
else
|
||||||
|
startDownload(p.second, url);
|
||||||
} else {
|
} else {
|
||||||
startDownload(p.second, url);
|
startDownload(p.second, url);
|
||||||
}
|
}
|
||||||
} else {
|
} catch (const LMDBAL::NotFound& e) {
|
||||||
startDownload(p.second, url);
|
|
||||||
}
|
|
||||||
} catch (const Archive::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";
|
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);
|
storage.addFile(url);
|
||||||
startDownload(std::list<Shared::MessageInfo>(), url);
|
startDownload(std::list<Shared::MessageInfo>(), url);
|
||||||
} catch (const Archive::Unknown& e) {
|
} catch (const LMDBAL::Unknown& e) {
|
||||||
qDebug() << "Error requesting file path:" << e.what();
|
qDebug() << "Error requesting file path:" << e.what();
|
||||||
emit loadFileError(std::list<Shared::MessageInfo>(), QString("Database error: ") + e.what(), false);
|
emit loadFileError(std::list<Shared::MessageInfo>(), QString("Database error: ") + e.what(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::start()
|
void Core::NetworkAccess::start() {
|
||||||
{
|
|
||||||
if (!running) {
|
if (!running) {
|
||||||
manager = new QNetworkAccessManager();
|
manager = new QNetworkAccessManager();
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
#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) {
|
if (running) {
|
||||||
storage.close();
|
storage.close();
|
||||||
manager->deleteLater();
|
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<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Transfer*>::const_iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::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";
|
qDebug() << "DEBUG: DOWNLOAD ERROR";
|
||||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
qDebug() << rpl->errorString();
|
qDebug() << rpl->errorString();
|
||||||
@ -134,8 +127,7 @@ void Core::NetworkAccess::onDownloadError(QNetworkReply::NetworkError code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::onDownloadSSLError(const QList<QSslError>& errors)
|
void Core::NetworkAccess::onDownloadSSLError(const QList<QSslError>& errors) {
|
||||||
{
|
|
||||||
qDebug() << "DEBUG: DOWNLOAD SSL ERRORS";
|
qDebug() << "DEBUG: DOWNLOAD SSL ERRORS";
|
||||||
for (const QSslError& err : errors) {
|
for (const QSslError& err : errors) {
|
||||||
qDebug() << err.errorString();
|
qDebug() << err.errorString();
|
||||||
@ -154,9 +146,7 @@ void Core::NetworkAccess::onDownloadSSLError(const QList<QSslError>& errors)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code) {
|
||||||
QString Core::NetworkAccess::getErrorText(QNetworkReply::NetworkError code)
|
|
||||||
{
|
|
||||||
QString errorText("");
|
QString errorText("");
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case QNetworkReply::NoError:
|
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";
|
qDebug() << "DEBUG: DOWNLOAD FINISHED";
|
||||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
@ -296,11 +285,11 @@ void Core::NetworkAccess::onDownloadFinished()
|
|||||||
QStringList hops = url.split("/");
|
QStringList hops = url.split("/");
|
||||||
QString fileName = hops.back();
|
QString fileName = hops.back();
|
||||||
QString jid;
|
QString jid;
|
||||||
if (dwn->messages.size() > 0) {
|
if (dwn->messages.size() > 0)
|
||||||
jid = dwn->messages.front().jid;
|
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";
|
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);
|
QString path = prepareDirectory(jid);
|
||||||
if (path.size() > 0) {
|
if (path.size() > 0) {
|
||||||
path = checkFileName(fileName, path);
|
path = checkFileName(fileName, path);
|
||||||
@ -319,12 +308,11 @@ void Core::NetworkAccess::onDownloadFinished()
|
|||||||
err = "Couldn't prepare a directory for file";
|
err = "Couldn't prepare a directory for file";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.size() > 0) {
|
if (path.size() > 0)
|
||||||
emit downloadFileComplete(dwn->messages, path);
|
emit downloadFileComplete(dwn->messages, path);
|
||||||
} else {
|
else
|
||||||
emit loadFileError(dwn->messages, "Error saving file " + url + "; " + err, false);
|
emit loadFileError(dwn->messages, "Error saving file " + url + "; " + err, false);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dwn->reply->deleteLater();
|
dwn->reply->deleteLater();
|
||||||
delete dwn;
|
delete dwn;
|
||||||
@ -332,8 +320,7 @@ void Core::NetworkAccess::onDownloadFinished()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::startDownload(const std::list<Shared::MessageInfo>& msgs, const QString& url)
|
void Core::NetworkAccess::startDownload(const std::list<Shared::MessageInfo>& msgs, const QString& url) {
|
||||||
{
|
|
||||||
Transfer* dwn = new Transfer({msgs, 0, 0, true, "", url, 0});
|
Transfer* dwn = new Transfer({msgs, 0, 0, true, "", url, 0});
|
||||||
QNetworkRequest req(url);
|
QNetworkRequest req(url);
|
||||||
dwn->reply = manager->get(req);
|
dwn->reply = manager->get(req);
|
||||||
@ -349,8 +336,7 @@ void Core::NetworkAccess::startDownload(const std::list<Shared::MessageInfo>& ms
|
|||||||
emit loadFileProgress(dwn->messages, 0, false);
|
emit loadFileProgress(dwn->messages, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code)
|
void Core::NetworkAccess::onUploadError(QNetworkReply::NetworkError code) {
|
||||||
{
|
|
||||||
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
std::map<QString, Transfer*>::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<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
||||||
@ -389,21 +374,17 @@ void Core::NetworkAccess::onUploadFinished()
|
|||||||
|
|
||||||
// Copy {TEMPDIR}/squawk_img_attach_XXXXXX.png to Download folder
|
// Copy {TEMPDIR}/squawk_img_attach_XXXXXX.png to Download folder
|
||||||
bool copyResult = QFile::copy(upl->path, Shared::resolvePath(newPath));
|
bool copyResult = QFile::copy(upl->path, Shared::resolvePath(newPath));
|
||||||
|
if (copyResult)
|
||||||
if (copyResult) {
|
upl->path = newPath; // Change storage
|
||||||
// Change storage
|
else
|
||||||
upl->path = newPath;
|
|
||||||
} else {
|
|
||||||
err = "copying to " + newPath + " failed";
|
err = "copying to " + newPath + " failed";
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
err = "Couldn't prepare a directory for file";
|
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;
|
qDebug() << "failed to copy temporary upload file " << upl->path << " to download folder:" << err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
storage.addFile(upl->messages, upl->url, upl->path);
|
storage.addFile(upl->messages, upl->url, upl->path);
|
||||||
emit uploadFileComplete(upl->messages, upl->url, upl->path);
|
emit uploadFileComplete(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<QNetworkReply*>(sender());
|
QNetworkReply* rpl = static_cast<QNetworkReply*>(sender());
|
||||||
QString url = rpl->url().toString();
|
QString url = rpl->url().toString();
|
||||||
std::map<QString, Transfer*>::const_iterator itr = uploads.find(url);
|
std::map<QString, Transfer*>::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);
|
QString p = Shared::squawkifyPath(path);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
p = storage.getUrl(p);
|
p = storage.getUrl(p);
|
||||||
} catch (const Archive::NotFound& err) {
|
} catch (const LMDBAL::NotFound& err) {
|
||||||
p = "";
|
p = "";
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
throw;
|
throw;
|
||||||
@ -451,8 +430,13 @@ QString Core::NetworkAccess::getFileRemoteUrl(const QString& path)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::uploadFile(const Shared::MessageInfo& info, 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);
|
QFile* file = new QFile(path);
|
||||||
Transfer* upl = new Transfer({{info}, 0, 0, true, path, get.toString(), file});
|
Transfer* upl = new Transfer({{info}, 0, 0, true, path, get.toString(), file});
|
||||||
QNetworkRequest req(put);
|
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);
|
storage.addFile(url, account, jid, id);
|
||||||
std::map<QString, Transfer*>::iterator itr = downloads.find(url);
|
std::map<QString, Transfer*>::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?
|
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);
|
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<const QString, Transfer*>& pair : uploads) {
|
for (const std::pair<const QString, Transfer*>& pair : uploads) {
|
||||||
Transfer* info = pair.second;
|
Transfer* info = pair.second;
|
||||||
if (pair.second->path == path) {
|
if (pair.second->path == path) {
|
||||||
@ -516,8 +496,7 @@ bool Core::NetworkAccess::checkAndAddToUploading(const QString& acc, const QStri
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Core::NetworkAccess::prepareDirectory(const QString& jid)
|
QString Core::NetworkAccess::prepareDirectory(const QString& jid) {
|
||||||
{
|
|
||||||
QString path = currentPath;
|
QString path = currentPath;
|
||||||
QString addition;
|
QString addition;
|
||||||
if (jid.size() > 0) {
|
if (jid.size() > 0) {
|
||||||
@ -529,25 +508,23 @@ QString Core::NetworkAccess::prepareDirectory(const QString& jid)
|
|||||||
|
|
||||||
if (!location.exists()) {
|
if (!location.exists()) {
|
||||||
bool res = location.mkpath(path);
|
bool res = location.mkpath(path);
|
||||||
if (!res) {
|
if (!res)
|
||||||
return "";
|
return "";
|
||||||
} else {
|
else
|
||||||
return "squawk://" + addition;
|
return "squawk://" + addition;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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(".");
|
QStringList parts = name.split(".");
|
||||||
QString suffix("");
|
QString suffix("");
|
||||||
QStringList::const_iterator sItr = parts.begin();
|
QStringList::const_iterator sItr = parts.begin();
|
||||||
QString realName = *sItr;
|
QString realName = *sItr;
|
||||||
++sItr;
|
++sItr;
|
||||||
for (QStringList::const_iterator sEnd = parts.end(); sItr != sEnd; ++sItr) {
|
for (QStringList::const_iterator sEnd = parts.end(); sItr != sEnd; ++sItr)
|
||||||
suffix += "." + (*sItr);
|
suffix += "." + (*sItr);
|
||||||
}
|
|
||||||
QString postfix("");
|
QString postfix("");
|
||||||
QString resolvedPath = Shared::resolvePath(path);
|
QString resolvedPath = Shared::resolvePath(path);
|
||||||
QString count("");
|
QString count("");
|
||||||
@ -562,18 +539,15 @@ QString Core::NetworkAccess::checkFileName(const QString& name, const QString& p
|
|||||||
return path + QDir::separator() + realName + count + suffix;
|
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);
|
return storage.addMessageAndCheckForPath(url, account, jid, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Shared::MessageInfo> Core::NetworkAccess::reportPathInvalid(const QString& path)
|
std::list<Shared::MessageInfo> Core::NetworkAccess::reportPathInvalid(const QString& path) {
|
||||||
{
|
|
||||||
return storage.deletedFile(path);
|
return storage.deletedFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::NetworkAccess::moveFilesDirectory(const QString& newPath)
|
void Core::NetworkAccess::moveFilesDirectory(const QString& newPath) {
|
||||||
{
|
|
||||||
QDir dir(currentPath);
|
QDir dir(currentPath);
|
||||||
bool success = true;
|
bool success = true;
|
||||||
qDebug() << "moving" << currentPath << "to" << newPath;
|
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;
|
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";
|
qDebug() << "couldn't move downloads directory, most probably downloads will be broken";
|
||||||
}
|
|
||||||
currentPath = newPath;
|
currentPath = newPath;
|
||||||
}
|
}
|
||||||
|
@ -30,15 +30,11 @@
|
|||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <core/storage/urlstorage.h>
|
|
||||||
#include <shared/pathcheck.h>
|
#include <shared/pathcheck.h>
|
||||||
|
#include "urlstorage.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo write docs
|
|
||||||
*/
|
|
||||||
|
|
||||||
//TODO Need to describe how to get rid of records when file is no longer reachable;
|
//TODO Need to describe how to get rid of records when file is no longer reachable;
|
||||||
class NetworkAccess : public QObject
|
class NetworkAccess : public QObject
|
||||||
{
|
{
|
||||||
|
289
core/components/urlstorage.cpp
Normal file
289
core/components/urlstorage.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
* Squawk messenger.
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "urlstorage.h"
|
||||||
|
|
||||||
|
Core::UrlStorage::UrlStorage(const QString& p_name):
|
||||||
|
base(p_name),
|
||||||
|
urlToInfo(base.addStorage<QString, UrlInfo>("urlToInfo")),
|
||||||
|
pathToUrl(base.addStorage<QString, QString>("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<Shared::MessageInfo>& 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<Shared::MessageInfo> Core::UrlStorage::setPath(const QString& url, const QString& path) {
|
||||||
|
std::list<Shared::MessageInfo> 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<Shared::MessageInfo> Core::UrlStorage::removeFile(const QString& url) {
|
||||||
|
std::list<Shared::MessageInfo> 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<Shared::MessageInfo> Core::UrlStorage::deletedFile(const QString& path) {
|
||||||
|
std::list<Shared::MessageInfo> 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<QString, std::list<Shared::MessageInfo>> Core::UrlStorage::getPath(const QString& url) {
|
||||||
|
UrlInfo info = urlToInfo->getRecord(url);
|
||||||
|
std::list<Shared::MessageInfo> 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<Shared::MessageInfo>& 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<Shared::MessageInfo>::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<Shared::MessageInfo>& 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;
|
||||||
|
}
|
@ -21,20 +21,19 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <lmdb.h>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "archive.h"
|
#include <storage.h>
|
||||||
|
|
||||||
#include <shared/messageinfo.h>
|
#include <shared/messageinfo.h>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
/**
|
class UrlStorage {
|
||||||
* @todo write docs
|
public:
|
||||||
*/
|
|
||||||
class UrlStorage
|
|
||||||
{
|
|
||||||
class UrlInfo;
|
class UrlInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UrlStorage(const QString& name);
|
UrlStorage(const QString& name);
|
||||||
~UrlStorage();
|
~UrlStorage();
|
||||||
@ -55,20 +54,16 @@ public:
|
|||||||
std::pair<QString, std::list<Shared::MessageInfo>> getPath(const QString& url);
|
std::pair<QString, std::list<Shared::MessageInfo>> getPath(const QString& url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString name;
|
LMDBAL::Base base;
|
||||||
bool opened;
|
LMDBAL::Storage<QString, UrlInfo>* urlToInfo;
|
||||||
MDB_env* environment;
|
LMDBAL::Storage<QString, QString>* pathToUrl;
|
||||||
MDB_dbi base;
|
|
||||||
MDB_dbi map;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeInfo(const QString& key, const UrlInfo& info, bool overwrite = false);
|
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 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");
|
UrlInfo addToInfo(const QString& url, const QString& account, const QString& jid, const QString& id, const QString& path = "-s");
|
||||||
|
|
||||||
private:
|
public:
|
||||||
class UrlInfo {
|
class UrlInfo {
|
||||||
public:
|
public:
|
||||||
UrlInfo(const QString& path);
|
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
|
#endif // CORE_URLSTORAGE_H
|
@ -1,10 +1,4 @@
|
|||||||
target_sources(squawk PRIVATE
|
target_sources(squawk PRIVATE
|
||||||
archive.cpp
|
archive.cpp
|
||||||
archive.h
|
archive.h
|
||||||
# storage.hpp
|
|
||||||
# storage.h
|
|
||||||
urlstorage.cpp
|
|
||||||
urlstorage.h
|
|
||||||
# cache.hpp
|
|
||||||
# cache.h
|
|
||||||
)
|
)
|
||||||
|
@ -1,491 +0,0 @@
|
|||||||
/*
|
|
||||||
* Squawk messenger.
|
|
||||||
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#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<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)
|
|
||||||
{
|
|
||||||
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<Shared::MessageInfo> Core::UrlStorage::setPath(const QString& url, const QString& path)
|
|
||||||
{
|
|
||||||
std::list<Shared::MessageInfo> 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<Shared::MessageInfo> Core::UrlStorage::removeFile(const QString& url)
|
|
||||||
{
|
|
||||||
std::list<Shared::MessageInfo> 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<Shared::MessageInfo> Core::UrlStorage::deletedFile(const QString& path)
|
|
||||||
{
|
|
||||||
std::list<Shared::MessageInfo> 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<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() {}
|
|
||||||
|
|
||||||
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() {}
|
|
||||||
|
|
||||||
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<Shared::MessageInfo>::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<Shared::MessageInfo>& 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;
|
|
||||||
}
|
|
2
external/qxmpp
vendored
2
external/qxmpp
vendored
@ -1 +1 @@
|
|||||||
Subproject commit d679ad1c49eeb28be2ac3a75bd7fd1a9be24d483
|
Subproject commit ab4bdf2da41a26f462fe3a333a34e32c999e2a6d
|
@ -43,6 +43,7 @@ int main(int argc, char *argv[])
|
|||||||
qRegisterMetaType<Shared::EncryptionProtocol>("Shared::EncryptionProtocol");
|
qRegisterMetaType<Shared::EncryptionProtocol>("Shared::EncryptionProtocol");
|
||||||
qRegisterMetaType<Shared::KeyInfo>("Shared::KeyInfo");
|
qRegisterMetaType<Shared::KeyInfo>("Shared::KeyInfo");
|
||||||
qRegisterMetaType<Shared::Info>("Shared::Info");
|
qRegisterMetaType<Shared::Info>("Shared::Info");
|
||||||
|
qRegisterMetaType<Shared::TrustLevel>("Shared::TrustLevel");
|
||||||
#ifdef WITH_OMEMO
|
#ifdef WITH_OMEMO
|
||||||
qRegisterMetaType<QXmppOmemoStorage::OwnDevice>("QXmppOmemoStorage::OwnDevice");
|
qRegisterMetaType<QXmppOmemoStorage::OwnDevice>("QXmppOmemoStorage::OwnDevice");
|
||||||
qRegisterMetaTypeStreamOperators<QXmppOmemoStorage::OwnDevice>("QXmppOmemoStorage::OwnDevice");
|
qRegisterMetaTypeStreamOperators<QXmppOmemoStorage::OwnDevice>("QXmppOmemoStorage::OwnDevice");
|
||||||
@ -53,7 +54,6 @@ int main(int argc, char *argv[])
|
|||||||
if (!app.initializeSettings())
|
if (!app.initializeSettings())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
return app.run();
|
return app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user