mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-20 21:33:27 -07:00
Add platform-specific handling. Add Win reserved name chacking for CON,PRN etc
This commit is contained in:
parent
365e1e6f56
commit
149bdad285
2 changed files with 55 additions and 18 deletions
|
@ -54,8 +54,6 @@
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
|
||||||
#include "base/utils/string.h"
|
|
||||||
#include "torrentcontentmodelfile.h"
|
#include "torrentcontentmodelfile.h"
|
||||||
#include "torrentcontentmodelfolder.h"
|
#include "torrentcontentmodelfolder.h"
|
||||||
#include "torrentcontentmodelitem.h"
|
#include "torrentcontentmodelitem.h"
|
||||||
|
@ -275,6 +273,56 @@ int TorrentContentModel::columnCount([[maybe_unused]] const QModelIndex &parent)
|
||||||
return TorrentContentModelItem::NB_COL;
|
return TorrentContentModelItem::NB_COL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validates a file name, where "file" refers to both files and directories in Windows and Unix-like systems.
|
||||||
|
// Rejects empty or special names (".", ".."), platform-specific lengths or reserved names, and forbidden characters.
|
||||||
|
bool TorrentContentModel::isInvalidName(const QString &name) const
|
||||||
|
{
|
||||||
|
// Reject empty names or special directory names (".", "..")
|
||||||
|
if (name.isEmpty() || name == u"."_s || name == u".."_s)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Windows restricts file names to 255 characters and prohibits trailing dots
|
||||||
|
if (name.length() > 255 || name.endsWith(u'.'))
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
// Non-Windows systems limit file name lengths to 255 bytes in UTF-8 encoding
|
||||||
|
if (name.toUtf8().length() > 255)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Windows reserves certain names for devices, which cannot be used as file names
|
||||||
|
static const QStringList reservedNames {
|
||||||
|
QStringLiteral("CON"), QStringLiteral("PRN"), QStringLiteral("AUX"), QStringLiteral("NUL"),
|
||||||
|
QStringLiteral("COM1"), QStringLiteral("COM2"), QStringLiteral("COM3"), QStringLiteral("COM4"),
|
||||||
|
QStringLiteral("COM5"), QStringLiteral("COM6"), QStringLiteral("COM7"), QStringLiteral("COM8"),
|
||||||
|
QStringLiteral("COM9"), QStringLiteral("COM¹"), QStringLiteral("COM²"), QStringLiteral("COM³"),
|
||||||
|
QStringLiteral("LPT1"), QStringLiteral("LPT2"), QStringLiteral("LPT3"), QStringLiteral("LPT4"),
|
||||||
|
QStringLiteral("LPT5"), QStringLiteral("LPT6"), QStringLiteral("LPT7"), QStringLiteral("LPT8"),
|
||||||
|
QStringLiteral("LPT9"), QStringLiteral("LPT¹"), QStringLiteral("LPT²"), QStringLiteral("LPT³")
|
||||||
|
};
|
||||||
|
const QString baseName = name.section(u'.', 0, 0);
|
||||||
|
if (reservedNames.contains(baseName, Qt::CaseInsensitive))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check for control characters, delete character and forward slash
|
||||||
|
for (const QChar &c : name)
|
||||||
|
{
|
||||||
|
const ushort unicode = c.unicode();
|
||||||
|
if (unicode < 32 || unicode == 127 || c == u'/')
|
||||||
|
return true;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Windows forbids reserved characters in file names
|
||||||
|
if (c == u'\\' || c == u'<' || c == u'>' || c == u':' || c == u'"' ||
|
||||||
|
c == u'|' || c == u'?' || c == u'*')
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &value, const int role)
|
bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &value, const int role)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
|
@ -301,28 +349,16 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
|
||||||
case TorrentContentModelItem::COL_NAME:
|
case TorrentContentModelItem::COL_NAME:
|
||||||
{
|
{
|
||||||
const QString currentName = item->name();
|
const QString currentName = item->name();
|
||||||
QString newName = value.toString().trimmed();
|
const QString newName = value.toString().trimmed();
|
||||||
|
|
||||||
if (currentName != newName)
|
if (currentName != newName)
|
||||||
{
|
{
|
||||||
bool invalid = newName.isEmpty() || (newName == u"."_s) || (newName == u".."_s) || (newName.length() > 255) || newName.endsWith(u'.');
|
if (isInvalidName(newName))
|
||||||
if (!invalid)
|
|
||||||
{
|
|
||||||
for (const QChar &c : newName)
|
|
||||||
{
|
|
||||||
const ushort unicode = c.unicode();
|
|
||||||
if ((unicode < 32) || (unicode == 127) || (c == u'<') || (c == u'>') || (c == u':') || (c == u'"') || (c == u'/') || (c == u'\\') || (c == u'|') || (c == u'?') || (c == u'*'))
|
|
||||||
{
|
|
||||||
invalid = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (invalid)
|
|
||||||
{
|
{
|
||||||
emit renameFailed(tr("The name \"%1\" is invalid.").arg(newName));
|
emit renameFailed(tr("The name \"%1\" is invalid.").arg(newName));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const Path parentPath = getItemPath(index.parent());
|
const Path parentPath = getItemPath(index.parent());
|
||||||
|
|
|
@ -94,6 +94,7 @@ private:
|
||||||
void updateFilesPriorities();
|
void updateFilesPriorities();
|
||||||
void updateFilesAvailability();
|
void updateFilesAvailability();
|
||||||
bool setItemPriority(const QModelIndex &index, BitTorrent::DownloadPriority priority);
|
bool setItemPriority(const QModelIndex &index, BitTorrent::DownloadPriority priority);
|
||||||
|
bool isInvalidName(const QString &name) const;
|
||||||
void notifySubtreeUpdated(const QModelIndex &index, const QList<ColumnInterval> &columns);
|
void notifySubtreeUpdated(const QModelIndex &index, const QList<ColumnInterval> &columns);
|
||||||
|
|
||||||
BitTorrent::TorrentContentHandler *m_contentHandler = nullptr;
|
BitTorrent::TorrentContentHandler *m_contentHandler = nullptr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue