Sync: Add capability for invalid filename regexes #6092

This commit is contained in:
Christian Kamm 2017-10-13 14:56:40 +02:00 committed by Markus Goetz
parent af24b4132d
commit bf39343920
4 changed files with 59 additions and 4 deletions

View file

@ -145,4 +145,9 @@ QList<int> Capabilities::httpErrorCodesThatResetFailingChunkedUploads() const
}
return list;
}
QString Capabilities::invalidFilenameRegex() const
{
return _capabilities["dav"].toMap()["invalidFilenameRegex"].toString();
}
}

View file

@ -105,6 +105,17 @@ public:
*/
QList<int> httpErrorCodesThatResetFailingChunkedUploads() const;
/**
* Regex that, if contained in a filename, will result in it not being uploaded.
*
* For servers older than 8.1.0 it defaults to [\\:?*"<>|]
* For servers >= that version, it defaults to the empty regex (the server
* will indicate invalid characters through an upload error)
*
* Note that it just needs to be contained. The regex [ab] is contained in "car".
*/
QString invalidFilenameRegex() const;
private:
QVariantMap _capabilities;
};

View file

@ -960,11 +960,20 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
}
// Check for invalid character in old server version
if (_account->serverVersionInt() < Account::makeServerVersion(8, 1, 0)) {
// Server version older than 8.1 don't support these character in filename.
static const QRegExp invalidCharRx("[\\\\:?*\"<>|]");
QString invalidFilenamePattern = _account->capabilities().invalidFilenameRegex();
if (invalidFilenamePattern.isNull()
&& _account->serverVersionInt() < Account::makeServerVersion(8, 1, 0)) {
// Server versions older than 8.1 don't support some characters in filenames.
// If the capability is not set, default to a pattern that avoids uploading
// files with names that contain these.
// It's important to respect the capability also for older servers -- the
// version check doesn't make sense for custom servers.
invalidFilenamePattern = "[\\\\:?*\"<>|]";
}
if (!invalidFilenamePattern.isEmpty()) {
const QRegExp invalidFilenameRx(invalidFilenamePattern);
for (auto it = syncItems.begin(); it != syncItems.end(); ++it) {
if ((*it)->_direction == SyncFileItem::Up && (*it)->destination().contains(invalidCharRx)) {
if ((*it)->_direction == SyncFileItem::Up && (*it)->destination().contains(invalidFilenameRx)) {
(*it)->_errorString = tr("File name contains at least one invalid character");
(*it)->_instruction = CSYNC_INSTRUCTION_IGNORE;
}

View file

@ -667,6 +667,36 @@ private slots:
fakeFolder.remoteModifier().create("A/a6", 16, 'A');
QVERIFY(!fakeFolder.syncOnce());
}
// Tests the behavior of invalid filename detection
void testInvalidFilenameRegex()
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
// For current servers, no characters are forbidden
fakeFolder.syncEngine().account()->setServerVersion("10.0.0");
fakeFolder.localModifier().insert("A/\\:?*\"<>|.txt");
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
// For legacy servers, some characters were forbidden by the client
fakeFolder.syncEngine().account()->setServerVersion("8.0.0");
fakeFolder.localModifier().insert("B/\\:?*\"<>|.txt");
QVERIFY(fakeFolder.syncOnce());
QVERIFY(!fakeFolder.currentRemoteState().find("B/\\:?*\"<>|.txt"));
// We can override that by setting the capability
fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ { "invalidFilenameRegex", "" } } } });
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
// Check that new servers also accept the capability
fakeFolder.syncEngine().account()->setServerVersion("10.0.0");
fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ { "invalidFilenameRegex", "my[fgh]ile" } } } });
fakeFolder.localModifier().insert("C/myfile.txt");
QVERIFY(fakeFolder.syncOnce());
QVERIFY(!fakeFolder.currentRemoteState().find("C/myfile.txt"));
}
};
QTEST_GUILESS_MAIN(TestSyncEngine)