From 46fc8904ec917bf7aff2812b7cadc9617a11d677 Mon Sep 17 00:00:00 2001 From: Bart De Vries Date: Thu, 6 Jul 2023 14:56:33 +0200 Subject: [PATCH] Restrict filenames to alphanumeric characters --- src/database.cpp | 9 +++++++-- src/storagemanager.cpp | 17 ++++++++++++++++- src/storagemanager.h | 2 ++ src/updatefeedjob.cpp | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/database.cpp b/src/database.cpp index 633626d2..e1b0749a 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -191,7 +192,8 @@ bool Database::migrateTo8() QString name = query.value(QStringLiteral("name")).toString(); // Generate directory name for enclosures based on feed name - QString dirBaseName = name.left(maxFilenameLength); + QString dirBaseName = name.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9 ._()-]"))).simplified().left(maxFilenameLength); + dirBaseName = dirBaseName.isEmpty() ? QStringLiteral("Noname") : dirBaseName; QString dirName = dirBaseName; // Check for duplicate names @@ -226,8 +228,11 @@ bool Database::migrateTo8() if (QFileInfo::exists(legacyPath) && QFileInfo(legacyPath).isFile()) { // Generate filename based on episode name and url hash with feedname as subdirectory - QString enclosureFilenameBase = queryTitle.left(maxFilenameLength) + QStringLiteral(".") + QString enclosureFilenameBase = queryTitle.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9 ._()-]"))).simplified().left(maxFilenameLength); + enclosureFilenameBase = enclosureFilenameBase.isEmpty() ? QStringLiteral("Noname") : enclosureFilenameBase; + enclosureFilenameBase += QStringLiteral(".") + QString::fromStdString(QCryptographicHash::hash(queryUrl.toUtf8(), QCryptographicHash::Md5).toHex().toStdString()).left(6); + QString enclosureFilenameExt = QFileInfo(QUrl::fromUserInput(queryUrl).fileName()).suffix(); QString enclosureFilename = diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index f90b505e..c0467fe3 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "enclosure.h" @@ -138,8 +139,9 @@ QString StorageManager::enclosureDirPath(const QString &feedname) const QString StorageManager::enclosurePath(const QString &name, const QString &url, const QString &feedname) const { // Generate filename based on episode name and url hash with feedname as subdirectory - QString enclosureFilenameBase = name.left(maxFilenameLength) + QStringLiteral(".") + QString enclosureFilenameBase = sanitizedFilePath(name) + QStringLiteral(".") + QString::fromStdString(QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5).toHex().toStdString()).left(6); + QString enclosureFilenameExt = QFileInfo(QUrl::fromUserInput(url).fileName()).suffix(); QString enclosureFilename = !enclosureFilenameExt.isEmpty() ? enclosureFilenameBase + QStringLiteral(".") + enclosureFilenameExt : enclosureFilenameBase; @@ -205,3 +207,16 @@ QString StorageManager::passwordFilePath(const QString &username) const { return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/") + username; } + +QString StorageManager::sanitizedFilePath(const QString &path) const +{ + // NOTE: Any changes here require a database migration! + + // Only keep alphanumeric ascii characters; this avoid any kind of issues + // with the many types of filesystems out there. Then remove excess whitespace + // and limit the length of the string. + QString newPath = path; + newPath = newPath.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9 ._()-]"))).simplified().left(maxFilenameLength); + + return newPath.isEmpty() ? QStringLiteral("Noname") : newPath; +} diff --git a/src/storagemanager.h b/src/storagemanager.h index 8a2484e4..0dd3f02d 100644 --- a/src/storagemanager.h +++ b/src/storagemanager.h @@ -56,6 +56,8 @@ public: QString passwordFilePath(const QString &username) const; + QString sanitizedFilePath(const QString &path) const; + Q_SIGNALS: void error(Error::Type type, const QString &url, const QString &id, const int errorId, const QString &errorString, const QString &title); diff --git a/src/updatefeedjob.cpp b/src/updatefeedjob.cpp index 2aba8c78..494dcacd 100644 --- a/src/updatefeedjob.cpp +++ b/src/updatefeedjob.cpp @@ -698,7 +698,7 @@ QString UpdateFeedJob::generateFeedDirname(const QString &name) const { // Generate directory name for enclosures based on feed name // NOTE: Any changes here require a database migration! - QString dirBaseName = name.left(StorageManager::maxFilenameLength); + QString dirBaseName = StorageManager::instance().sanitizedFilePath(name); QString dirName = dirBaseName; QStringList dirNameList;