QDir: strip Windows' long-path markers when converting from native

Applications might receive paths with Windows' '\\?\' markers, which
indicates a long path to Win32 APIs, when the application is opened by
explorer via file association. Qt not ignoring those markers will fail
to open such files.

By stripping the marker in QDir::fromNativeSeparators, QFile, QFileInfo
etc automatically are able to handle such paths. QDir::cleanPath is
also documented to normalize separators, so it needs to be done there
as well.

[ChangeLog][QtCore][QDir] Remove Windows specific long path markers
when handling file paths with native separators.

Change-Id: I526a890614edee8c85b39fc12c98e7ddb6e0d793
Fixes: QTBUG-75117
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Volker Hilsheimer 2019-07-09 16:50:15 +02:00
parent a7d7f71550
commit 3966b571ff
2 changed files with 13 additions and 0 deletions

View File

@ -947,6 +947,12 @@ QString QDir::fromNativeSeparators(const QString &pathName)
int i = pathName.indexOf(QLatin1Char('\\'));
if (i != -1) {
QString n(pathName);
if (n.startsWith(QLatin1String("\\\\?\\"))) {
n.remove(0, 4);
i = n.indexOf(QLatin1Char('\\'));
if (i == -1)
return n;
}
QChar * const data = n.data();
data[i++] = QLatin1Char('/');
@ -2339,6 +2345,11 @@ static QString qt_cleanPath(const QString &path, bool *ok)
if (path.isEmpty())
return path;
QString name = path;
#if defined (Q_OS_WIN)
if (name.startsWith(QLatin1String("\\\\?\\")))
name.remove(0, 4);
#endif
QChar dir_separator = QDir::separator();
if (dir_separator != QLatin1Char('/'))
name.replace(dir_separator, QLatin1Char('/'));

View File

@ -1268,6 +1268,7 @@ tst_QDir::cleanPath_data()
QTest::newRow("drive-above-root") << "A:/.." << "A:/..";
QTest::newRow("unc-server-up") << "//server/path/.." << "//server";
QTest::newRow("unc-server-above-root") << "//server/.." << "//server/..";
QTest::newRow("longpath") << "\\\\?\\d:\\" << "d:/";
#else
QTest::newRow("data15") << "//c:/foo" << "/c:/foo";
#endif // non-windows
@ -1745,6 +1746,7 @@ void tst_QDir::nativeSeparators()
QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("/")), QString("/"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\")), QString("/"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\\\?\\C:\\")), QString("C:/"));
#else
QCOMPARE(QDir::toNativeSeparators(QLatin1String("/")), QString("/"));
QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\"));