diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-12-29 15:56:33 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-12-30 12:09:53 +0100 |
commit | db92f2f3aac60218756a1aa8811cf192acc0b0e6 (patch) | |
tree | f28a47aebb2f08e221fe7bffafce62a0a96cf7fd /src/corelib/io | |
parent | dd61a1d98ea9fbffeaf0e2adcd0ddd58105f6a75 (diff) | |
parent | 44da5b863597e761df3545dc7ff02a9b53bbb13d (diff) |
Merge remote-tracking branch 'origin/5.9' into 5.10
Conflicts:
.qmake.conf
mkspecs/win32-g++/qmake.conf
src/corelib/global/qglobal_p.h
src/corelib/global/qoperatingsystemversion_p.h
src/corelib/io/qfilesystemengine_win.cpp
src/network/bearer/qbearerengine.cpp
src/platformsupport/input/libinput/qlibinputpointer.cpp
src/sql/doc/snippets/code/doc_src_sql-driver.cpp
src/widgets/kernel/qwidget_p.h
src/widgets/kernel/qwidgetwindow.cpp
src/widgets/styles/qfusionstyle.cpp
tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
Change-Id: I80e2722f481b12fff5d967c28f89208c0e9a1dd8
Diffstat (limited to 'src/corelib/io')
-rwxr-xr-x[-rw-r--r--] | src/corelib/io/qfilesystemengine_win.cpp | 64 | ||||
-rw-r--r-- | src/corelib/io/qloggingregistry.cpp | 4 | ||||
-rw-r--r-- | src/corelib/io/qloggingregistry_p.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qurl.cpp | 110 |
4 files changed, 163 insertions, 17 deletions
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 944ca232ee..fadc058110 100644..100755 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -160,6 +160,7 @@ static TRUSTEE_W currentUserTrusteeW; static TRUSTEE_W worldTrusteeW; static PSID currentUserSID = 0; static PSID worldSID = 0; +static HANDLE currentUserImpersonatedToken = nullptr; QT_BEGIN_NAMESPACE @@ -180,6 +181,11 @@ GlobalSid::~GlobalSid() ::FreeSid(worldSID); worldSID = 0; } + + if (currentUserImpersonatedToken) { + ::CloseHandle(currentUserImpersonatedToken); + currentUserImpersonatedToken = nullptr; + } } GlobalSid::GlobalSid() @@ -210,6 +216,12 @@ GlobalSid::GlobalSid() ::CloseHandle(token); } + token = nullptr; + if (::OpenProcessToken(hnd, TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &token)) { + ::DuplicateToken(token, SecurityImpersonation, ¤tUserImpersonatedToken); + ::CloseHandle(token); + } + { // Create TRUSTEE for Everyone (World) SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY }; @@ -724,15 +736,49 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst ACCESS_MASK access_mask; TRUSTEE_W trustee; if (what & QFileSystemMetaData::UserPermissions) { // user - data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; - if (GetEffectiveRightsFromAcl(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) - access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - data.entryFlags |= QFileSystemMetaData::UserReadPermission; - if(access_mask & WriteMask) - data.entryFlags|= QFileSystemMetaData::UserWritePermission; - if(access_mask & ExecMask) - data.entryFlags|= QFileSystemMetaData::UserExecutePermission; + // Using AccessCheck because GetEffectiveRightsFromAcl doesn't account for elevation + if (currentUserImpersonatedToken) { + GENERIC_MAPPING mapping = {FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS}; + PRIVILEGE_SET privileges; + DWORD grantedAccess; + BOOL result; + + data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; + DWORD genericAccessRights = GENERIC_READ; + ::MapGenericMask(&genericAccessRights, &mapping); + + DWORD privilegesLength = sizeof(privileges); + if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights, + &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) { + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + } + + privilegesLength = sizeof(privileges); + genericAccessRights = GENERIC_WRITE; + ::MapGenericMask(&genericAccessRights, &mapping); + if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights, + &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) { + data.entryFlags |= QFileSystemMetaData::UserWritePermission; + } + + privilegesLength = sizeof(privileges); + genericAccessRights = GENERIC_EXECUTE; + ::MapGenericMask(&genericAccessRights, &mapping); + if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights, + &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) { + data.entryFlags |= QFileSystemMetaData::UserExecutePermission; + } + } else { // fallback to GetEffectiveRightsFromAcl + data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; + if (GetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) + access_mask = ACCESS_MASK(-1); + if (access_mask & ReadMask) + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + if (access_mask & WriteMask) + data.entryFlags|= QFileSystemMetaData::UserWritePermission; + if (access_mask & ExecMask) + data.entryFlags|= QFileSystemMetaData::UserExecutePermission; + } } if (what & QFileSystemMetaData::OwnerPermissions) { // owner data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions; diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 1bf61017f6..b5f8e30b80 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -255,7 +255,7 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line) QLoggingRegistry::QLoggingRegistry() : categoryFilter(defaultCategoryFilter) { - initalizeRules(); // Init on first use + initializeRules(); // Init on first use } static bool qtLoggingDebug() @@ -284,7 +284,7 @@ static QVector<QLoggingRule> loadRulesFromFile(const QString &filePath) Initializes the rules database by loading $QT_LOGGING_CONF, $QT_LOGGING_RULES, and .config/QtProject/qtlogging.ini. */ -void QLoggingRegistry::initalizeRules() +void QLoggingRegistry::initializeRules() { QVector<QLoggingRule> er, qr, cr; // get rules from environment diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index a3857d3588..12a1f166b3 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -113,7 +113,7 @@ class Q_AUTOTEST_EXPORT QLoggingRegistry public: QLoggingRegistry(); - void initalizeRules(); + void initializeRules(); void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel); void unregisterCategory(QLoggingCategory *category); diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index cf7ed130ba..4587b9fcd6 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -90,11 +90,6 @@ fromPercentEncoding() and toPercentEncoding() which deal with percent encoding and decoding of QString objects. - Calling isRelative() will tell whether or not the URL is - relative. A relative URL can be resolved by passing it as argument - to resolved(), which returns an absolute URL. isParentOf() is used - for determining whether one URL is a parent of another. - fromLocalFile() constructs a QUrl by parsing a local file path. toLocalFile() converts a URL to a local file path. @@ -116,6 +111,37 @@ from freedesktop.org, provided that the locale encodes file names using UTF-8 (required by IDN). + \section2 Relative URLs vs Relative Paths + + Calling isRelative() will return whether or not the URL is relative. + A relative URL has no \l {scheme}. For example: + + \code + qDebug() << QUrl("main.qml").isRelative(); // true: no scheme + qDebug() << QUrl("qml/main.qml").isRelative(); // true: no scheme + qDebug() << QUrl("file:main.qml").isRelative(); // false: has "file" scheme + qDebug() << QUrl("file:qml/main.qml").isRelative(); // false: has "file" scheme + \endcode + + Notice that a URL can be absolute while containing a relative path, and + vice versa: + + \code + // Absolute URL, relative path + QUrl url("file:file.txt"); + qDebug() << url.isRelative(); // false: has "file" scheme + qDebug() << QDir::isAbsolutePath(url.path()); // false: relative path + + // Relative URL, absolute path + url = QUrl("/home/user/file.txt"); + qDebug() << url.isRelative(); // true: has no scheme + qDebug() << QDir::isAbsolutePath(url.path()); // true: absolute path + \endcode + + A relative URL can be resolved by passing it as an argument to resolved(), + which returns an absolute URL. isParentOf() is used for determining whether + one URL is a parent of another. + \section2 Error checking QUrl is capable of detecting many errors in URLs while parsing it or when @@ -2539,6 +2565,12 @@ void QUrl::setPath(const QString &path, ParsingMode mode) /*! Returns the path of the URL. + \code + qDebug() << QUrl("file:file.txt").path(); // "file.txt" + qDebug() << QUrl("/home/user/file.txt").path(); // "/home/user/file.txt" + qDebug() << QUrl("http://www.example.com/test/123").path(); // "/test/123" + \endcode + The \a options argument controls how to format the path component. All values produce an unambiguous result. With QUrl::FullyDecoded, all percent-encoded sequences are decoded; otherwise, the returned value may @@ -2549,6 +2581,31 @@ void QUrl::setPath(const QString &path, ParsingMode mode) sequences are present. It is recommended to use that value when the result will be used in a non-URL context, such as sending to an FTP server. + An example of data loss is when you have non-Unicode percent-encoded sequences + and use FullyDecoded (the default): + + \code + qDebug() << QUrl("/foo%FFbar").path(); + \endcode + + In this example, there will be some level of data loss because the \c %FF cannot + be converted. + + Data loss can also occur when the path contains sub-delimiters (such as \c +): + + \code + qDebug() << QUrl("/foo+bar%2B").path(); // "/foo+bar+" + \endcode + + Other decoding examples: + + \code + const QUrl url("/tmp/Mambo %235%3F.mp3"); + qDebug() << url.path(QUrl::FullyDecoded); // "/tmp/Mambo #5?.mp3" + qDebug() << url.path(QUrl::PrettyDecoded); // "/tmp/Mambo #5?.mp3" + qDebug() << url.path(QUrl::FullyEncoded); // "/tmp/Mambo%20%235%3F.mp3" + \endcode + \sa setPath() */ QString QUrl::path(ComponentFormattingOptions options) const @@ -3257,6 +3314,8 @@ QUrl QUrl::resolved(const QUrl &relative) const equivalent to calling scheme().isEmpty(). Relative references are defined in RFC 3986 section 4.2. + + \sa {Relative URLs vs Relative Paths} */ bool QUrl::isRelative() const { @@ -3796,6 +3855,41 @@ bool QUrl::isDetached() const An empty \a localFile leads to an empty URL (since Qt 5.4). + \code + qDebug() << QUrl::fromLocalFile("file.txt"); // QUrl("file:file.txt") + qDebug() << QUrl::fromLocalFile("/home/user/file.txt"); // QUrl("file:///home/user/file.txt") + qDebug() << QUrl::fromLocalFile("file:file.txt"); // doesn't make sense; expects path, not url with scheme + \endcode + + In the first line in snippet above, a file URL is constructed from a + local, relative path. A file URL with a relative path only makes sense + if there is a base URL to resolve it against. For example: + + \code + QUrl url = QUrl::fromLocalFile("file.txt"); + QUrl baseUrl = QUrl("file:/home/user/"); + // wrong: prints QUrl("file:file.txt"), as url already has a scheme + qDebug() << baseUrl.resolved(url); + \endcode + + To resolve such a URL, it's necessary to remove the scheme beforehand: + + \code + // correct: prints QUrl("file:///home/user/file.txt") + url.setScheme(QString()); + qDebug() << baseUrl.resolved(url); + \endcode + + For this reason, it is better to use a relative URL (that is, no scheme) + for relative file paths: + + \code + QUrl url = QUrl("file.txt"); + QUrl baseUrl = QUrl("file:/home/user/"); + // prints QUrl("file:///home/user/file.txt") + qDebug() << baseUrl.resolved(url); + \endcode + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators() */ QUrl QUrl::fromLocalFile(const QString &localFile) @@ -3840,6 +3934,12 @@ QUrl QUrl::fromLocalFile(const QString &localFile) returned value in the form found on SMB networks (for example, "//servername/path/to/file.txt"). + \code + qDebug() << QUrl("file:file.txt").toLocalFile(); // "file:file.txt" + qDebug() << QUrl("file:/home/user/file.txt").toLocalFile(); // "file:///home/user/file.txt" + qDebug() << QUrl("file.txt").toLocalFile(); // ""; wasn't a local file as it had no scheme + \endcode + Note: if the path component of this URL contains a non-UTF-8 binary sequence (such as %80), the behaviour of this function is undefined. |