Skip to content

Conversation

@cocopaw
Copy link
Contributor

@cocopaw cocopaw commented Oct 16, 2025

Enhance filename validation

This PR extends [#23060] and implements the following key improvements:

  1. Refactor isValidFileName
  2. Enhance isValidPath to use new logic
  3. Enhance toValidFileName to use new logic
  4. Enhance toValidPath to use new logic
  5. Enhance Torrent Creator to use new logic

Testing

Tested: Windows 11 + Linux Mint 22.1


Fixes: #22426 #21899 #16906 #16834 #16271 #11276 #9085 #11340 #14728 #20412 #20337 #17049 #17469 #15378 #15227 #14908 #20742

else
{
path = Utils::Fs::toValidPath(categoryName);
path = Path(Utils::Fs::toValidFileName(categoryName));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the category name can represent a path, so you seem to have broken it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldnt fault itbwhen I was testing. I also tested subcategories. Can u give me an example scenario that would break it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldnt fault itbwhen I was testing. I also tested subcategories. Can u give me an example scenario that would break it?

Did you test it with "flat" categories (i.e. when subcategories is disabled)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it with both flat categories and subcategories.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it with both flat categories and subcategories.

Name like some/category/name is supposed to represent corresponding path some/category/name. Doesn't toValidFileName() replace slashes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok give me a few days and ill see what I can do.

Are you ok with Path.isvalid() being moved to fs utils and reworked too ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you ok with Path.isvalid() being moved to fs utils and reworked too ?

Ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a minor housekeeping side suggestion that I noticed whilst working on fs.cpp.

Are you ok with this suggestion too?

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions implemented as discussed.

@qBittUser
Copy link

1st commit title has typo: Refactor isValidName. Enahnce toValidFileName.

Should be written Enhance instead of Enahnce.

@cocopaw
Copy link
Contributor Author

cocopaw commented Oct 20, 2025

@Chocobo1 @glassez , ready for review.

Additional Notes:

  1. Incorrect terminology "Relevant issues:" had been used in previous PR Block invalid file names when renaming torrent content #23060 to list the cases to close on merge. In order to address this I have checked all the relevant cases and added them via "Fixes:" here.

    And outlier to this is Torrents with content names containing backslash (\) are mishandled on linux #17752 This issue was addressed via related Libtorrent PR of mine libtorrent issue 8014. The issue is in "Closed as not planned" status (incorrect) and locked to collaborators. Could someone please update it to add mention of libtorrent issue 8014 and mark it as fixed?

  2. For the commit Remove Utils::Fs::isValidFileName from TorrentsController::renameFileAction, the functions below invoke torrent->renameFile, which now performs validation via the new Path.isValid(). The prior isValidName checks in torrentcontentmodel.cpp are therefore redundant and have been removed.

src/gui/torrentcontentmodel.cpp
..
TorrentsController::renameFileAction
TorrentsController::renameFolderAction

@Chocobo1 Chocobo1 added the Core label Oct 20, 2025
Comment on lines -1993 to -1996
const QString newFileName = QFileInfo(params()[u"newPath"_s]).fileName();
if (!Utils::Fs::isValidName(newFileName))
throw APIError(APIErrorType::Conflict, tr("File name has invalid characters"));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove it? It should be checked anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Becuase it's a redundant check now. It is already checked downstream via BitTorrent::AbstractFileStorage::renameFile. Now that Path.isValid() is using the new logic we not longer need to check it via Utils::Fs::isValidName in torrentscontroller.cpp.

The error checking is also better via BitTorrent::AbstractFileStorage::renameFile as it is more descriptive (it specifies if the oldpath or newpath is invalid instead of just the whole thing)

Process Flow:

TorrentsController::renameFileAction() -> torrent->renameFile -> BitTorrent::AbstractFileStorage::renameFile -> oldPath.isValid()

void BitTorrent::AbstractFileStorage::renameFile(const Path &oldPath, const Path &newPath)
{
    if (!oldPath.isValid())
        throw RuntimeError(tr("The old path is invalid: '%1'.").arg(oldPath.toString()));
    if (!newPath.isValid())
        throw RuntimeError(tr("The new path is invalid: '%1'.").arg(newPath.toString()));
    if (newPath.isAbsolute())
        throw RuntimeError(tr("Absolute path isn't allowed: '%1'.").arg(newPath.toString()));

My previous comment (for reference):

For the commit "Remove Utils::Fs::isValidFileName from TorrentsController::renameFileAction", 
the functions below invoke "torrent->renameFile", which now performs validation via the 
new "Path.isValid()". The prior "isValidName" checks in torrentcontentmodel.cpp are therefore 
redundant and have been removed.

src/gui/torrentcontentmodel.cpp
..
TorrentsController::renameFileAction
TorrentsController::renameFolderAction

Comment on lines -2021 to -2024
const QString newFolderName = QFileInfo(params()[u"newPath"_s]).fileName();
if (!Utils::Fs::isValidName(newFolderName))
throw APIError(APIErrorType::Conflict, tr("Folder name has invalid characters"));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too.

const QRegularExpression regex {u"\\0"_s};
#endif
return !m_pathStr.contains(regex);
return Utils::Fs::isValidPath(*this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me that this change completely messed up Path class design.
I cannot understand the changes anymore. I'll stop here until things clears up.

Copy link
Contributor Author

@cocopaw cocopaw Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was agreed in the first review on this PR with glassez:

image

The thinking was to consolodate all file validation logic to FS Utils. This also has the benefit of allowing all related functions to share validation logic via the unamed namespace in fs.cpp.

I could just remove path.isValid() entirely from path.h and path.cpp and then change whatever was calling that to call Utils::Fs::isValidPath instead if preffered? *

* The reason I didn't do this initially is that:

  1. It is more changes
  2. I figured it would be good to keep the path.isValid method in path.h\path.cpp so that people can see it is available just by looking at path.h\path.cpp.

Can you expand on what you mean by "this change completely messed up Path class design" ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5.0.2 Linux Debian 12 - rename folder and files in payload entering slash / in name cause creating erroneous subfolders

4 participants