diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index d52bcdf9d42..4c816adb479 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -180,6 +180,11 @@ QString FilePath::encodedHost() const return result; } +QString decodeHost(QString host) +{ + return host.replace("%25", "%").replace("%2f", "/"); +} + /// \returns a QString for passing on to QString based APIs QString FilePath::toString() const { @@ -765,10 +770,10 @@ void FilePath::setFromString(const QString &unnormalizedFileName) const int firstSlash = withoutQtcDeviceRoot.indexOf(slash); if (firstSlash != -1) { - QString scheme = withoutQtcDeviceRoot.left(firstSlash).toString(); + const QString scheme = withoutQtcDeviceRoot.left(firstSlash).toString(); const int secondSlash = withoutQtcDeviceRoot.indexOf(slash, firstSlash + 1); - QString host = withoutQtcDeviceRoot.mid(firstSlash + 1, secondSlash - firstSlash - 1) - .toString(); + const QString host = decodeHost( + withoutQtcDeviceRoot.mid(firstSlash + 1, secondSlash - firstSlash - 1).toString()); if (secondSlash != -1) { QStringView path = withoutQtcDeviceRoot.mid(secondSlash); setParts(scheme, host, path); @@ -787,9 +792,9 @@ void FilePath::setFromString(const QString &unnormalizedFileName) const int schemeEnd = fileName.indexOf(colonSlashSlash); if (schemeEnd != -1 && schemeEnd < firstSlash) { // This is a pseudo Url, we can't use QUrl here sadly. - QString scheme = fileName.left(schemeEnd); + const QString scheme = fileName.left(schemeEnd); const int hostEnd = fileName.indexOf(slash, schemeEnd + 3); - QString host = fileName.mid(schemeEnd + 3, hostEnd - schemeEnd - 3); + const QString host = decodeHost(fileName.mid(schemeEnd + 3, hostEnd - schemeEnd - 3)); setParts(scheme, host, hostEnd != -1 ? QStringView(fileName).mid(hostEnd) : QStringView()); return; } diff --git a/tests/auto/utils/fileutils/tst_fileutils.cpp b/tests/auto/utils/fileutils/tst_fileutils.cpp index d4cd46965cf..5fb8fa2d0c7 100644 --- a/tests/auto/utils/fileutils/tst_fileutils.cpp +++ b/tests/auto/utils/fileutils/tst_fileutils.cpp @@ -104,6 +104,9 @@ private slots: void isSameFile_data(); void isSameFile(); + void hostSpecialChars_data(); + void hostSpecialChars(); + private: QTemporaryDir tempDir; QString rootPath; @@ -1159,6 +1162,54 @@ void tst_fileutils::isSameFile() QCOMPARE(left.isSameFile(right), shouldBeEqual); } +void tst_fileutils::hostSpecialChars_data() +{ + QTest::addColumn("scheme"); + QTest::addColumn("host"); + QTest::addColumn("path"); + QTest::addColumn("expected"); + + QTest::addRow("slash-in-host") << "device" << "host/name" << "/" << FilePath::fromString("device://host%2fname/"); + QTest::addRow("percent-in-host") << "device" << "host%name" << "/" << FilePath::fromString("device://host%25name/"); + QTest::addRow("percent-and-slash-in-host") << "device" << "host/%name" << "/" << FilePath::fromString("device://host%2f%25name/"); + QTest::addRow("qtc-dev-slash-in-host-linux") << "device" << "host/name" << "/" << FilePath::fromString("/__qtc_devices__/device/host%2fname/"); + QTest::addRow("qtc-dev-slash-in-host-windows") << "device" << "host/name" << "/" << FilePath::fromString("c:/__qtc_devices__/device/host%2fname/"); + +} + +void tst_fileutils::hostSpecialChars() +{ + QFETCH(QString, scheme); + QFETCH(QString, host); + QFETCH(QString, path); + QFETCH(FilePath, expected); + + FilePath fp; + fp.setParts(scheme, host, path); + + // Check that setParts and fromString give the same result + QCOMPARE(fp, expected); + QCOMPARE(fp.host(), expected.host()); + QCOMPARE(fp.host(), host); + QCOMPARE(expected.host(), host); + + QString toStringExpected = expected.toString(); + QString toStringActual = fp.toString(); + + // Check that toString gives the same result + QCOMPARE(toStringActual, toStringExpected); + + // Check that fromString => toString => fromString gives the same result + FilePath toFromExpected = FilePath::fromString(expected.toString()); + QCOMPARE(toFromExpected, expected); + QCOMPARE(toFromExpected, fp); + + // Check that setParts => toString => fromString gives the same result + FilePath toFromActual = FilePath::fromString(fp.toString()); + QCOMPARE(toFromActual, fp); + QCOMPARE(toFromExpected, expected); +} + QTEST_GUILESS_MAIN(tst_fileutils) #include "tst_fileutils.moc"