From 8f7ad48e963e54df1ee14c22f7c55388fb76bba1 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Mon, 5 Aug 2024 17:50:03 +0800 Subject: [PATCH 01/13] Parse forbidden filename related capability features Signed-off-by: Claudio Cambra --- src/libsync/capabilities.cpp | 20 ++++++++++++++++++++ src/libsync/capabilities.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/src/libsync/capabilities.cpp b/src/libsync/capabilities.cpp index 143608b30082f..f7b84716f2daa 100644 --- a/src/libsync/capabilities.cpp +++ b/src/libsync/capabilities.cpp @@ -404,6 +404,26 @@ QStringList Capabilities::blacklistedFiles() const return _capabilities["files"].toMap()["blacklisted_files"].toStringList(); } +QStringList Capabilities::forbiddenFilenames() const +{ + return _capabilities["files"].toMap()["forbidden_filenames"].toStringList(); +} + +QStringList Capabilities::forbiddenFilenameCharacters() const +{ + return _capabilities["files"].toMap()["forbidden_filename_characters"].toStringList(); +} + +QStringList Capabilities::forbiddenFilenameBasenames() const +{ + return _capabilities["files"].toMap()["forbidden_filename_basenames"].toStringList(); +} + +QStringList Capabilities::forbiddenFilenameExtensions() const +{ + return _capabilities["files"].toMap()["forbidden_filename_extensions"].toStringList(); +} + /*-------------------------------------------------------------------------------------*/ // Direct Editing diff --git a/src/libsync/capabilities.h b/src/libsync/capabilities.h index ca2cb7190c4b4..da10854528b30 100644 --- a/src/libsync/capabilities.h +++ b/src/libsync/capabilities.h @@ -166,6 +166,11 @@ class OWNCLOUDSYNC_EXPORT Capabilities */ [[nodiscard]] QStringList blacklistedFiles() const; + [[nodiscard]] QStringList forbiddenFilenameCharacters() const; + [[nodiscard]] QStringList forbiddenFilenameBasenames() const; + [[nodiscard]] QStringList forbiddenFilenameExtensions() const; + [[nodiscard]] QStringList forbiddenFilenames() const; + /** * Whether conflict files should remain local (default) or should be uploaded. */ From 29ab9ec95d00e6b64c807eefbb73177744fc411f Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Mon, 5 Aug 2024 17:50:46 +0800 Subject: [PATCH 02/13] Check for new forbidden filename-related capabilities during exclusion handling in discovery Signed-off-by: Claudio Cambra --- src/libsync/discovery.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index 2b55eaf1c1d2f..f910a55ae33f4 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -292,8 +292,23 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent } const auto &localName = entries.localEntry.name; + const auto splitName = localName.split('.'); + const auto &baseName = splitName.first(); + const auto extension = splitName.size() > 1 ? splitName.last() : QString(); + const auto accountCaps = _discoveryData->_account->capabilities(); + const auto forbiddenFilenames = accountCaps.forbiddenFilenames(); + const auto forbiddenBasenames = accountCaps.forbiddenFilenameBasenames(); + const auto forbiddenExtensions = accountCaps.forbiddenFilenameExtensions(); + const auto forbiddenChars = accountCaps.forbiddenFilenameCharacters(); + if (excluded == CSYNC_NOT_EXCLUDED && !localName.isEmpty() - && _discoveryData->_serverBlacklistedFiles.contains(localName)) { + && (_discoveryData->_serverBlacklistedFiles.contains(localName) + || forbiddenFilenames.contains(localName) + || forbiddenBasenames.contains(baseName) + || forbiddenExtensions.contains(extension) + || std::any_of(forbiddenChars.cbegin(), forbiddenChars.cend(), [&localName](const QString &charPattern) { + return localName.contains(charPattern); + }))) { excluded = CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED; isInvalidPattern = true; } From 071ab937afe92738e09df8f4b0bfbebce12314b3 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Mon, 5 Aug 2024 18:03:21 +0800 Subject: [PATCH 03/13] Add test for new forbidden filename capabilities Signed-off-by: Claudio Cambra --- test/testlocaldiscovery.cpp | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/testlocaldiscovery.cpp b/test/testlocaldiscovery.cpp index a3dc0d64d194a..7f5f4f0855ecc 100644 --- a/test/testlocaldiscovery.cpp +++ b/test/testlocaldiscovery.cpp @@ -294,6 +294,45 @@ private slots: QVERIFY(!fakeFolder.currentRemoteState().find("C/bar")); } + // Tests the behavior of forbidden filename detection + void testServerForbiddenFilenames() + { + FakeFolder fakeFolder { FileInfo::A12_B12_C12_S12() }; + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + fakeFolder.syncEngine().account()->setCapabilities({ + { "files", QVariantMap { + { "forbidden_filenames", QVariantList { ".foo", "bar" } }, + { "forbidden_filename_characters", QVariantList { "\n" } }, + { "forbidden_filename_basenames", QVariantList { "base" } }, + { "forbidden_filename_extensions", QVariantList { "ext" } } + } } + }); + + fakeFolder.localModifier().insert("C/.foo"); + fakeFolder.localModifier().insert("C/bar"); + fakeFolder.localModifier().insert("C/moo"); + fakeFolder.localModifier().insert("C/.moo"); + fakeFolder.localModifier().insert("C/potatopotato.txt"); + fakeFolder.localModifier().insert("C/potato\npotato.txt"); + fakeFolder.localModifier().insert("C/basefilename.txt"); + fakeFolder.localModifier().insert("C/base.txt"); + fakeFolder.localModifier().insert("C/filename.txt"); + fakeFolder.localModifier().insert("C/filename.ext"); + + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(fakeFolder.currentRemoteState().find("C/moo")); + QVERIFY(fakeFolder.currentRemoteState().find("C/.moo")); + QVERIFY(!fakeFolder.currentRemoteState().find("C/.foo")); + QVERIFY(!fakeFolder.currentRemoteState().find("C/bar")); + QVERIFY(fakeFolder.currentRemoteState().find("C/potatopotato.txt")); + QVERIFY(!fakeFolder.currentRemoteState().find("C/potato\npotato.txt")); + QVERIFY(fakeFolder.currentRemoteState().find("C/basefilename.txt")); + QVERIFY(!fakeFolder.currentRemoteState().find("C/base.txt")); + QVERIFY(fakeFolder.currentRemoteState().find("C/filename.txt")); + QVERIFY(!fakeFolder.currentRemoteState().find("C/filename.ext")); + } + void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameAndUploadFile() { FakeFolder fakeFolder{FileInfo{}}; From eee3a090ccf97a535559abf21a4b5456a04bf98f Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 6 Aug 2024 14:34:41 +0800 Subject: [PATCH 04/13] Provide Windows-compatible forbidden filename character in forbidden filenames test Signed-off-by: Claudio Cambra --- test/testlocaldiscovery.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/testlocaldiscovery.cpp b/test/testlocaldiscovery.cpp index 7f5f4f0855ecc..11c7d2e0de0f6 100644 --- a/test/testlocaldiscovery.cpp +++ b/test/testlocaldiscovery.cpp @@ -303,7 +303,7 @@ private slots: fakeFolder.syncEngine().account()->setCapabilities({ { "files", QVariantMap { { "forbidden_filenames", QVariantList { ".foo", "bar" } }, - { "forbidden_filename_characters", QVariantList { "\n" } }, + { "forbidden_filename_characters", QVariantList { "_" } }, { "forbidden_filename_basenames", QVariantList { "base" } }, { "forbidden_filename_extensions", QVariantList { "ext" } } } } @@ -314,7 +314,7 @@ private slots: fakeFolder.localModifier().insert("C/moo"); fakeFolder.localModifier().insert("C/.moo"); fakeFolder.localModifier().insert("C/potatopotato.txt"); - fakeFolder.localModifier().insert("C/potato\npotato.txt"); + fakeFolder.localModifier().insert("C/potato_potato.txt"); fakeFolder.localModifier().insert("C/basefilename.txt"); fakeFolder.localModifier().insert("C/base.txt"); fakeFolder.localModifier().insert("C/filename.txt"); @@ -326,7 +326,7 @@ private slots: QVERIFY(!fakeFolder.currentRemoteState().find("C/.foo")); QVERIFY(!fakeFolder.currentRemoteState().find("C/bar")); QVERIFY(fakeFolder.currentRemoteState().find("C/potatopotato.txt")); - QVERIFY(!fakeFolder.currentRemoteState().find("C/potato\npotato.txt")); + QVERIFY(!fakeFolder.currentRemoteState().find("C/potato_potato.txt")); QVERIFY(fakeFolder.currentRemoteState().find("C/basefilename.txt")); QVERIFY(!fakeFolder.currentRemoteState().find("C/base.txt")); QVERIFY(fakeFolder.currentRemoteState().find("C/filename.txt")); From 1578cb19385e4b425db1d9d89bad747ff53bdb44 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 12:37:16 +0800 Subject: [PATCH 05/13] Assign invalid filename on server syncfileitem status to items with forbidden filenames Signed-off-by: Claudio Cambra --- src/libsync/discovery.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index f910a55ae33f4..0434ff9427fe8 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -416,6 +416,7 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent break; case CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED: item->_errorString = tr("The filename is blacklisted on the server."); + item->_status = SyncFileItem::FileNameInvalidOnServer; break; } } From eb189f8fb426e9d010ab9a700ece9808a8e94d59 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 15:22:57 +0800 Subject: [PATCH 06/13] Also provide notification for items that have file name invalid on server Signed-off-by: Claudio Cambra --- src/gui/tray/usermodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/tray/usermodel.cpp b/src/gui/tray/usermodel.cpp index 7ecf98a61f26c..2725471f16657 100644 --- a/src/gui/tray/usermodel.cpp +++ b/src/gui/tray/usermodel.cpp @@ -848,7 +848,7 @@ void User::processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr _activityModel->addIgnoredFileToList(activity); } else { // add 'protocol error' to activity list - if (item->_status == SyncFileItem::Status::FileNameInvalid) { + if (item->_status == SyncFileItem::Status::FileNameInvalid || item->_status == SyncFileItem::Status::FileNameInvalidOnServer) { showDesktopNotification(item->_file, activity._subject, activity._id); } else if (item->_status == SyncFileItem::Conflict || item->_status == SyncFileItem::FileNameClash) { ActivityLink buttonActivityLink; From a9dfc6ebfc1be3382f701cc5969269abd9db41d7 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 15:23:33 +0800 Subject: [PATCH 07/13] Add rename file link/button to invalid filename activities Signed-off-by: Claudio Cambra --- src/gui/tray/usermodel.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gui/tray/usermodel.cpp b/src/gui/tray/usermodel.cpp index 2725471f16657..296da16eb181b 100644 --- a/src/gui/tray/usermodel.cpp +++ b/src/gui/tray/usermodel.cpp @@ -849,6 +849,14 @@ void User::processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr } else { // add 'protocol error' to activity list if (item->_status == SyncFileItem::Status::FileNameInvalid || item->_status == SyncFileItem::Status::FileNameInvalidOnServer) { + ActivityLink buttonActivityLink; + buttonActivityLink._label = tr("Rename file"); + buttonActivityLink._link = activity._link.toString(); + buttonActivityLink._verb = "RENAME_LOCAL_FILE"; + buttonActivityLink._primary = true; + + activity._links = {buttonActivityLink}; + showDesktopNotification(item->_file, activity._subject, activity._id); } else if (item->_status == SyncFileItem::Conflict || item->_status == SyncFileItem::FileNameClash) { ActivityLink buttonActivityLink; From 94d62e020398af33e5cf955097ca4f57dda6df46 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 15:24:06 +0800 Subject: [PATCH 08/13] Handle invalid filename activities button verb in activity list model Signed-off-by: Claudio Cambra --- src/gui/tray/activitylistmodel.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp index 3976e9950c3c5..d00d1854cd2ae 100644 --- a/src/gui/tray/activitylistmodel.cpp +++ b/src/gui/tray/activitylistmodel.cpp @@ -840,9 +840,12 @@ void ActivityListModel::slotTriggerAction(const int activityIndex, const int act if (action._verb == "WEB") { Utility::openBrowser(QUrl(action._link)); return; - } else if (action._verb == "FIX_CONFLICT_LOCALLY" && - activity._type == Activity::SyncFileItemType && - (activity._syncFileItemStatus == SyncFileItem::Conflict || activity._syncFileItemStatus == SyncFileItem::FileNameClash)) { + } else if (((action._verb == "FIX_CONFLICT_LOCALLY" || action._verb == "RENAME_LOCAL_FILE") && + activity._type == Activity::SyncFileItemType && + (activity._syncFileItemStatus == SyncFileItem::Conflict || + activity._syncFileItemStatus == SyncFileItem::FileNameClash || + activity._syncFileItemStatus == SyncFileItem::FileNameInvalid || + activity._syncFileItemStatus == SyncFileItem::FileNameInvalidOnServer))) { slotTriggerDefaultAction(activityIndex); return; } else if (action._verb == ActivityLink::WhitelistFolderVerb && !activity._file.isEmpty()) { // _folder == folder alias/name, _file == folder/file path From f07b49288b532a7dcb88722398a8c0fb825f3cc2 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 16:22:08 +0800 Subject: [PATCH 09/13] Add invalid mode enum to invalid filename dialog Signed-off-by: Claudio Cambra --- src/gui/invalidfilenamedialog.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/invalidfilenamedialog.h b/src/gui/invalidfilenamedialog.h index f2552e5fc1080..1477dd6451fa7 100644 --- a/src/gui/invalidfilenamedialog.h +++ b/src/gui/invalidfilenamedialog.h @@ -39,8 +39,17 @@ class InvalidFilenameDialog : public QDialog Default = 0, NewLocalFile, }; + enum class InvalidMode { + SystemInvalid, + ServerInvalid + }; - explicit InvalidFilenameDialog(AccountPtr account, Folder *folder, QString filePath, FileLocation fileLocation = FileLocation::Default, QWidget *parent = nullptr); + explicit InvalidFilenameDialog(AccountPtr account, + Folder *folder, + QString filePath, + FileLocation fileLocation = FileLocation::Default, + InvalidMode invalidMode = InvalidMode::SystemInvalid, + QWidget *parent = nullptr); ~InvalidFilenameDialog() override; From aaf06535d20e9a2610412905b182c95230a61d1f Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 16:22:37 +0800 Subject: [PATCH 10/13] Provide different message and explanation strings in invalid filename dialog depending on invalid mode Signed-off-by: Claudio Cambra --- src/gui/invalidfilenamedialog.cpp | 40 ++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/gui/invalidfilenamedialog.cpp b/src/gui/invalidfilenamedialog.cpp index 844f5b5e4bdf2..f26a5161abcda 100644 --- a/src/gui/invalidfilenamedialog.cpp +++ b/src/gui/invalidfilenamedialog.cpp @@ -64,7 +64,12 @@ QString illegalCharacterListToString(const QVector &illegalCharacters) namespace OCC { -InvalidFilenameDialog::InvalidFilenameDialog(AccountPtr account, Folder *folder, QString filePath, FileLocation fileLocation, QWidget *parent) +InvalidFilenameDialog::InvalidFilenameDialog(AccountPtr account, + Folder *folder, + QString filePath, + FileLocation fileLocation, + InvalidMode invalidMode, + QWidget *parent) : QDialog(parent) , _ui(new Ui::InvalidFilenameDialog) , _account(account) @@ -89,8 +94,37 @@ InvalidFilenameDialog::InvalidFilenameDialog(AccountPtr account, Folder *folder, _ui->descriptionLabel->setTextFormat(Qt::PlainText); _ui->errorLabel->setTextFormat(Qt::PlainText); - _ui->descriptionLabel->setText(tr("The file \"%1\" could not be synced because the name contains characters which are not allowed on this system.").arg(_originalFileName)); - _ui->explanationLabel->setText(tr("The following characters are not allowed on the system: * \" | & ? , ; : \\ / ~ < > leading/trailing spaces")); + switch (invalidMode) { + case InvalidMode::SystemInvalid: + _ui->descriptionLabel->setText(tr("The file \"%1\" could not be synced because the name contains characters which are not allowed on this system.").arg(_originalFileName)); + _ui->explanationLabel->setText(tr("The following characters are not allowed on the system: * \" | & ? , ; : \\ / ~ < > leading/trailing spaces")); + break; + case InvalidMode::ServerInvalid: + _ui->descriptionLabel->setText(tr("The file \"%1\" could not be synced because the name contains characters which are not allowed on the server.").arg(_originalFileName)); + + const auto caps = _account->capabilities(); + const auto forbiddenCharacters = caps.forbiddenFilenameCharacters(); + const auto forbiddenBasenames = caps.forbiddenFilenameBasenames(); + const auto forbiddenFilenames = caps.forbiddenFilenames(); + const auto forbiddenExtensions = caps.forbiddenFilenameExtensions(); + + auto explanations = QStringList(); + + if (!forbiddenCharacters.isEmpty()) { + explanations.append(tr("The following characters are not allowed: %1").arg(forbiddenCharacters.join(" "))); + } + if (!forbiddenBasenames.isEmpty()) { + explanations.append(tr("The following basenames are not allowed: %1").arg(forbiddenBasenames.join(" "))); + } + if (!forbiddenFilenames.isEmpty()) { + explanations.append(tr("The following filenames are not allowed: %1").arg(forbiddenFilenames.join(" "))); + } + if (!forbiddenExtensions.isEmpty()) { + explanations.append(tr("The following file extensions are not allowed: %1").arg(forbiddenExtensions.join(" "))); + } + _ui->explanationLabel->setText(explanations.join("\n")); + break; + } _ui->filenameLineEdit->setText(filePathFileInfo.fileName()); connect(_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); From 598f2c95f5bee2ae8976d457560e716ccb7a1bff Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 16:22:49 +0800 Subject: [PATCH 11/13] Set invalid filename dialog mode in activity list model Signed-off-by: Claudio Cambra --- src/gui/tray/activitylistmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp index d00d1854cd2ae..61c05b8d8c796 100644 --- a/src/gui/tray/activitylistmodel.cpp +++ b/src/gui/tray/activitylistmodel.cpp @@ -729,9 +729,12 @@ void ActivityListModel::slotTriggerDefaultAction(const int activityIndex) const auto fileLocation = activity._syncFileItemStatus == SyncFileItem::FileNameInvalidOnServer ? InvalidFilenameDialog::FileLocation::NewLocalFile : InvalidFilenameDialog::FileLocation::Default; + const auto invalidMode = activity._syncFileItemStatus == SyncFileItem::FileNameInvalidOnServer + ? InvalidFilenameDialog::InvalidMode::ServerInvalid + : InvalidFilenameDialog::InvalidMode::SystemInvalid; _currentInvalidFilenameDialog = new InvalidFilenameDialog(_accountState->account(), folder, - folderDir.filePath(activity._file), fileLocation); + folderDir.filePath(activity._file), fileLocation, invalidMode); connect(_currentInvalidFilenameDialog, &InvalidFilenameDialog::accepted, folder, [folder]() { folder->scheduleThisFolderSoon(); }); From 788067598de0e089348ee592259eb347e3762079 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 22:01:05 +0800 Subject: [PATCH 12/13] Store forbidden filename match bools outside of if statement Signed-off-by: Claudio Cambra --- src/libsync/discovery.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index 0434ff9427fe8..a2c00fb29cc9a 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -301,14 +301,28 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent const auto forbiddenExtensions = accountCaps.forbiddenFilenameExtensions(); const auto forbiddenChars = accountCaps.forbiddenFilenameCharacters(); + const auto hasForbiddenFilename = forbiddenFilenames.contains(localName); + const auto hasForbiddenBasename = forbiddenBasenames.contains(baseName); + const auto hasForbiddenExtension = forbiddenExtensions.contains(extension); + + auto forbiddenCharMatch = QString{}; + const auto containsForbiddenCharacters = + std::any_of(forbiddenChars.cbegin(), + forbiddenChars.cend(), + [&localName, &forbiddenCharMatch](const QString &charPattern) { + if (localName.contains(charPattern)) { + forbiddenCharMatch = charPattern; + return true; + } + return false; + }); + if (excluded == CSYNC_NOT_EXCLUDED && !localName.isEmpty() && (_discoveryData->_serverBlacklistedFiles.contains(localName) - || forbiddenFilenames.contains(localName) - || forbiddenBasenames.contains(baseName) - || forbiddenExtensions.contains(extension) - || std::any_of(forbiddenChars.cbegin(), forbiddenChars.cend(), [&localName](const QString &charPattern) { - return localName.contains(charPattern); - }))) { + || hasForbiddenFilename + || hasForbiddenBasename + || hasForbiddenExtension + || containsForbiddenCharacters)) { excluded = CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED; isInvalidPattern = true; } From abb1f89119bd25e887cf8a8b769423c07d0fbf95 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 20 Aug 2024 22:01:34 +0800 Subject: [PATCH 13/13] When forbidden filename sync warning is encountered, add reason why the filename is forbidden to the item's error string Signed-off-by: Claudio Cambra --- src/libsync/discovery.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index a2c00fb29cc9a..089717f621684 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -430,6 +430,18 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent break; case CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED: item->_errorString = tr("The filename is blacklisted on the server."); + if (hasForbiddenFilename) { + item->_errorString += tr(" Reason: the entire filename is forbidden."); + } + if (hasForbiddenBasename) { + item->_errorString += tr(" Reason: the filename has a forbidden base name (filename start)."); + } + if (hasForbiddenExtension) { + item->_errorString += tr(" Reason: the file has a forbidden extension (.%1).").arg(extension); + } + if (containsForbiddenCharacters) { + item->_errorString += tr(" Reason: the filename contains a forbidden character (%1).").arg(forbiddenCharMatch); + } item->_status = SyncFileItem::FileNameInvalidOnServer; break; }