From 4f6c840ed171c1bdab2e894d46f1f57815bd9479 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 9 Oct 2024 02:19:35 +0200 Subject: [PATCH] Fix media deletion of animated files --- src/MxcImageProvider.cpp | 28 ++++++++++++++++++++++++---- src/timeline/TimelineModel.cpp | 10 ++++++---- src/ui/MxcAnimatedImage.cpp | 10 ++++++---- src/ui/MxcMediaProxy.cpp | 10 ++++++---- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp index 8d1ac01e..5684cf98 100644 --- a/src/MxcImageProvider.cpp +++ b/src/MxcImageProvider.cpp @@ -32,16 +32,17 @@ MxcImageProvider::MxcImageProvider() timer->setInterval(std::chrono::hours(1)); connect(timer, &QTimer::timeout, this, [] { QThreadPool::globalInstance()->start([] { + nhlog::net()->debug("Running media purge"); QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/media_cache", "", QDir::SortFlags(QDir::Name | QDir::IgnoreCase), - QDir::Filter::Writable | QDir::Filter::NoDotAndDotDot | QDir::Filter::Files); + QDir::Filter::Writable | QDir::Filter::NoDotAndDotDot | QDir::Filter::Files | + QDir::Filter::Dirs); - auto files = dir.entryInfoList(); - for (const auto &fileInfo : std::as_const(files)) { + auto handleFile = [](const QFileInfo &fileInfo) { if (fileInfo.fileTime(QFile::FileTime::FileAccessTime) - .daysTo(QDateTime::currentDateTime()) > 30) { + .daysTo(QDateTime::currentDateTime()) > 14) { if (QFile::remove(fileInfo.absoluteFilePath())) nhlog::net()->debug("Deleted stale media '{}'", fileInfo.absoluteFilePath().toStdString()); @@ -49,6 +50,25 @@ MxcImageProvider::MxcImageProvider() nhlog::net()->warn("Failed to delete stale media '{}'", fileInfo.absoluteFilePath().toStdString()); } + }; + + auto files = dir.entryInfoList(); + for (const auto &fileInfo : std::as_const(files)) { + if (fileInfo.isDir()) { + // handle one level of legacy directories + auto nestedDir = QDir(fileInfo.absoluteFilePath(), + "", + QDir::SortFlags(QDir::Name | QDir::IgnoreCase), + QDir::Filter::Writable | QDir::Filter::NoDotAndDotDot | + QDir::Filter::Files + ) + .entryInfoList(); + for (const auto &nestedFile : std::as_const(nestedDir)) { + handleFile(nestedFile); + } + } else { + handleFile(fileInfo); + } } }); }); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index eea345b5..33a984b3 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -2073,10 +2073,12 @@ TimelineModel::cacheMedia(const QString &eventId, const auto url = mxcUrl.toStdString(); const auto name = QString(mxcUrl).remove(QStringLiteral("mxc://")); - QFileInfo filename( - QStringLiteral("%1/media_cache/%2.%3") - .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), name, suffix)); - if (QDir::cleanPath(name) != name) { + QFileInfo filename(QStringLiteral("%1/media_cache/%2.%3") + .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), + QString::fromUtf8(name.toUtf8().toBase64( + QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)), + suffix)); + if (QDir::cleanPath(filename.filePath()) != filename.filePath()) { nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url); return; } diff --git a/src/ui/MxcAnimatedImage.cpp b/src/ui/MxcAnimatedImage.cpp index e58f2e6e..bd6a935d 100644 --- a/src/ui/MxcAnimatedImage.cpp +++ b/src/ui/MxcAnimatedImage.cpp @@ -53,10 +53,12 @@ MxcAnimatedImage::startDownload() const auto url = mxcUrl.toStdString(); const auto name = QString(mxcUrl).remove(QStringLiteral("mxc://")); - QFileInfo filename( - QStringLiteral("%1/media_cache/media/%2.%3") - .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), name, suffix)); - if (QDir::cleanPath(name) != name) { + QFileInfo filename(QStringLiteral("%1/media_cache/media/%2.%3") + .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), + QString::fromUtf8(name.toUtf8().toBase64( + QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)), + suffix)); + if (QDir::cleanPath(filename.filePath()) != filename.filePath()) { nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url); return; } diff --git a/src/ui/MxcMediaProxy.cpp b/src/ui/MxcMediaProxy.cpp index 3773b141..275af9bf 100644 --- a/src/ui/MxcMediaProxy.cpp +++ b/src/ui/MxcMediaProxy.cpp @@ -96,10 +96,12 @@ MxcMediaProxy::startDownload(bool onlyCached) const auto url = mxcUrl.toStdString(); const auto name = QString(mxcUrl).remove(QStringLiteral("mxc://")); - QFileInfo filename( - QStringLiteral("%1/media_cache/media/%2.%3") - .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), name, suffix)); - if (QDir::cleanPath(name) != name) { + QFileInfo filename(QStringLiteral("%1/media_cache/media/%2.%3") + .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), + QString::fromUtf8(name.toUtf8().toBase64( + QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)), + suffix)); + if (QDir::cleanPath(filename.filePath()) != filename.filePath()) { nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url); return; }